I'm trying to do invoice four, but I couldn't quite figure out how to do it.
First of all, to give an example:
Quantity 1 Unit Price 2000 Percent (18) = net total "2360".
and then if the user changes "net_total" I want the unit price to change.
Then if the user wants to apply a discount, I want it to be reflected in net_total as a percentage, or if he writes it as a currency, not a percentage. It will write net total.
const app = new Vue({
el: "#app",
data: {
invoiceItem: [
{
name: "",
quantity: 0,
unit_price: 0,
vat_rate: 18,
net_total: 0,
showDesc: false,
showDiscount: false,
description: '',
discount_value: 0,
discount_rate:'usd'
},
],
},
methods: {
addInvoice() {
this.invoiceItem.push({
name: "",
quantity: 0,
unit_price: 0,
vat_rate: 18,
net_total: 0,
showDesc: false,
showDiscount: false,
description: '',
discount_value: 0,
discount_rate:'usd'
});
},
removeIncoiceItem(index) {
this.invoiceItem.splice(index, 1);
},
},
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<div id="app">
<section class="container">
<div class="row">
<table class="table">
<thead class="thead-dark">
<tr>
<th style="width:17%">Name</th>
<th style="width:14%">Quantity</th>
<th style="width:14%">Unit Price</th>
<th style="width:15%">Vat Rate</th>
<th style="width:14%">Net Total</th>
<th style="width:15%">Action</th>
</tr>
</thead>
</table>
<div v-for="(item, index) in invoiceItem" :key="index" style="margin-bottom: 10px">
<div class="row">
<div class="col-md-2">
<input type="text" v-model="item.name">
</div>
<div class="col-md-2">
<input type="text" v-model="item.quantity">
</div>
<div class="col-md-2">
<input type="text" v-model="item.unit_price">
</div>
<div class="col-md-1">
<select v-model="item.vat_rate">
<option value="18">%18</option>
<option value="8">%8</option>
<option value="1">%1</option>
<option value="0">%0</option>
</select>
</div>
<div class="col-md-2">
<input type="text" v-model="item.net_total">
</div>
<div class="col-md-3">
<button
class="btn btn-primary"
v-if="!item.showDesc" #click="item.showDesc = !item.showDesc">Add Description
</button>
<button
class="btn btn-secondary"
v-if="!item.showDiscount" #click="item.showDiscount = !item.showDiscount">Add Discount
</button>
<button class="btn btn-danger" #click="removeIncoiceItem(index)">X</button>
</div>
<div class="col-md-4" v-if="item.showDesc">
<input type="text" placeholder="description">
</div>
<div class="col-md-4" v-if="item.showDiscount">
<div class="input-group">
<input type="text" placeholder="discount_value">
<select class="form-select-new" v-model="item.discount_rate">
<option value="dollar">USD</option> <option value="percent">&</option>
</select>
</div>
</div>
</div>
<hr>
</div>
<hr>
<div style="margin-top:10px">
<button class="btn btn-warning" #click="addInvoice()"> Add Item</button>
</div>
</div>
</section>
</div>
The easiest would be to create two calculate methods, one when the net_total changed and one when one of the parameters (like the unit_price) changed. I assume your unit_price is the gross unit price.
You have to add the #change property on the inputs.
<div class="col-md-2">
<input type="text" v-model="item.unit_price" #change="changed(item)">
</div>
<!-- ... -->
<div class="col-md-2">
<input type="text" v-model="item.net_total" #change="changedTotal(item)">
</div>
<!--
Here was also the 'v-model="item.discount_value"' missing.
<input type="text" placeholder="discount_value" v-model="item.discount_value" #change="changed(item)">
-->
<!--
<input type="text" v-model="item.quantity" #change="changed(item)">
<input type="text" v-model="item.unit_price" #change="changed(item)">
<select v-model="item.vat_rate" #change="changed(item)">
<input type="text" v-model="item.net_total" #change="changedTotal(item)">
<select class="form-select-new" v-model="item.discount_rate" #change="changed(item)">
-->
An then use the following methods to calculate the gross to net and net to gross.
changed(item) {
let sum = item.quantity * item.unit_price;
if (item.discount_rate == 'percent')
sum -= sum*parseFloat((item.discount_value / 100))
else
sum -= item.discount_value
let percent = parseFloat((item.vat_rate/100)+1);
item.net_total = sum/percent;
},
changedTotal(item) {
let percent = parseFloat((item.vat_rate/100)+1);
var gross = item.net_total * percent;
if (item.discount_rate == 'percent')
gross = gross*parseFloat((item.discount_value / 100)+1)
else
gross += item.discount_value
item.unit_price = gross / item.quantity;
},
It could also be possible via the vue watchers, but I think this would be too complicated.
Related
I am trying to make invoice transactions with vue js. my question is; The user may want to write a description for 1 product or may want to apply a discount. (BY REQUEST) I want the specified input to be shown whichever item he wants to add. (EVERY LINE CAN HAVE ONLY 1 EXPLANATION, DISCOUNT)
Therefore
on demand
When you press the "DESCRIPTION, DISCOUNT AND DISCOUNT RATE" buttons, the input of the relevant line will be pushed."
Thank you in advance for your help.
jsfiddle
const app = new Vue({
el: "#app",
data: {
invoiceItems: [
{
name: "",
quantity: 0,
unit_price: 0,
vat_rate: 18,
net_total: 0,
description: '',
discount_value: 0,
discount_rate:'usd'
},
],
},
methods: {
addInvoice() {
this.invoiceItems.push({
name: "",
quantity: 0,
unit_price: 0,
vat_rate: 18,
net_total: 0,
description: '',
discount_value: 0,
discount_rate:'usd'
});
},
removeIncoiceItem(index) {
this.invoiceItems.splice(index, 1);
},
},
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<div id="app">
<section class="container">
<div class="row">
<table class="table">
<thead class="thead-dark">
<tr>
<th style="width:17%">Name</th>
<th style="width:14%">Unit Price</th>
<th style="width:15%">Vat Rate</th>
<th style="width:20%">Action</th>
</tr>
</thead>
</table>
<div v-for="(item, index) in invoiceItems" :key="index" style="margin-bottom: 10px">
<div class="row">
<div class="col-md-2">
<input type="text" v-model="item.name">
</div>
<div class="col-md-2">
<input type="text" v-model="item.unit_price">
</div>
<div class="col-md-2">
<input type="text" v-model="item.net_total">
</div>
<div class="col-md-5">
<button class="btn btn-primary btn-sm">Add Description</button>
<button class="btn btn-secondary btn-sm">Add Discount</button>
<button class="btn btn-warning btn-sm">Add discount rate</button>
<button class="btn btn-danger btn-sm" #click="removeIncoiceItem(index)">X</button>
</div>
<div class="row" style="margin-top:20px;">
<div class="col-md-2">
<input type="text" placeholder="description">
</div>
<div class="col-md-2">
<button class="btn btn-danger btn-sm">Delete Desc.</button>
</div>
<div class="col-md-3">
<div class="input-group">
<input type="text" placeholder="discount_value">
<select class="form-select-new">
<option value="dollar">USD</option>
<option value="percent">&</option>
</select>
</div>
</div>
<div class="col-md-1">
<button class="btn btn-danger btn-sm">Delete Disc.</button>
</div>
<div class="col-md-2">
<input type="text" placeholder="discount rate">
</div>
<div class="col-md-2">
<button class="btn btn-danger btn-sm">Delete discount rate</button>
</div>
</div>
</div>
<hr>
</div>
<hr>
<div style="margin-top:10px">
<button class="btn btn-warning" #click="addInvoice()"> Add Item</button>
</div>
</div>
</section>
</div>
To show the input only when you press a button you should use v-if and check if the key exist on the item.
I will show you an example for description but you can apply it to all the inputs you want.
So when you add new item, add it without description like so:
methods: {
addInvoice() {
this.invoiceItems.push({
name: "",
quantity: 0,
unit_price: 0,
vat_rate: 18,
net_total: 0,
});
},
},
And check if item.description exists on the input of description:
<div class="col-md-2">
<input type="text" v-if="item.description !== undefined" v-model="item.description" placeholder="description"> </div>
...
<button class="btn btn-primary btn-sm" #click="addDesc(index)" >Add Description</button>
...
<div class="col-md-2">
<button class="btn btn-danger btn-sm" #click="deleteDesc(index)" >Delete Desc.</button>
</div>
The addDesc method will add the key to the item and set it as empty:
addDesc(index){
Vue.set(this.invoiceItems[index], "description", "");
}
The deleteDesc method will remove the key entirely from the item:
deleteDesc(index){
Vue.delete(this.invoiceItems[index], "description");
}
Now when you click on add description button - the description input will appear, and when you click delete description button - the description input will disappear.
there was a point where I got stuck while trying to make invoice transactions with vue js, I can add a new item, it works fine, the problem starts here, when I want to show the "description" and "discount_value" that I have hidden, it adds it to all lines, not like this, whichever index button is clicked. add his item. Thank you in advance for your help.
const app = new Vue({
el: '#app',
data: {
addAciklama: false,
addIndirim: false,
faturasections: [
{
name: "",
unit_price: 0,
net_total: 0,
description: '',
discount_value: '',
}
],
},
methods: {
addNewFaturaSatiri() {
this.faturasections.push({
name: "",
unit_price: 0,
net_total: 0,
description: '',
discount_value: '',
});
},
removeFaturaSatiri(faturasectionIndex) {
this.faturasections.splice(faturasectionIndex, 1);
},
}
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<div id="app">
<section>
<div class="card-body border-bottom-light" v-for="(fatura, faturasectionIndex) in faturasections" :key="faturasectionIndex">
<div class="row">
<div class="col-sm-4 col-12 mb-1 mb-sm-0 hizmet">
<div class="form-floating">
<input type="text" class="form-control" v-model="fatura.name" placeholder=" "/>
<label>HİZMET / ÜRÜN</label>
</div>
</div>
<div class="col-sm-2 col-12 mb-1 mb-sm-0 brfiyati">
<div class="form-floating">
<input type="number" class="form-control" v-model.number="fatura.unit_price" placeholder=" "/>
<label>BR.FİYAT</label>
</div>
</div>
<div class="col-sm-1 col-12 mb-1 mb-sm-0 toplam">
<div class="form-floating">
<input type="text" class="form-control" v-model="fatura.net_total" placeholder=" "/>
<label>TOPLAM</label>
</div>
</div>
<div class="col-sm-1 col-12 mb-1 mb-sm-0">
<div class="mb-1">
<div class="mb-1">
<button v-if="!addAciklama" #click="addAciklama = !addAciklama" class="dropdown-item">description</button>
<button v-if="!addIndirim" #click="addIndirim = !addIndirim" class="dropdown-item">discount_value</button>
</div>
</div>
<button class="btn btn-icon btn-secondary" #click="removeFaturaSatiri(faturasectionIndex)">DELETE</button>
</div>
</div>
<div id="aciklamalar" class="row mt-1">
<div class="col-12 d-flex">
<div class="col-sm-6 fatura-aciklama">
<div class="row" v-if="addAciklama">
<div class="f-a">
<div class="input-group">
<span class="input-group-text kdv">AÇIKLAMA</span>
<input type="text" class="form-control" v-model="fatura.description"/>
</div>
</div>
<div class="f-b">
<button class="btn btn-icon btn-outline-secondary" #click="addAciklama = !addAciklama">DELETE</button>
</div>
</div>
</div>
<div class="col-sm-5">
<div class="d-flex flex-column">
<div class="row row mb-1" v-if="addIndirim">
<div class="i-i">
<div class="input-group">
<span class="input-group-text kdv">İNDİRİM</span>
<input type="text" class="form-control" v-model="fatura.discount_value"/>
</div>
</div>
<div class="i-s">
<button class="btn btn-icon btn-outline-secondary" #click="addIndirim = !addIndirim">DELETE</button>
</div>
</div>
</div>
</div>
</div>
</div>
<hr>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-2">
<button type="button" class="btn btn-outline-secondary btn-sm"
data-repeater-create #click="addNewFaturaSatiri()">
<span class="align-middle">NEW INVOICE</span>
</button>
</div>
</div>
</div>
</section>
</div>
addAciklama and addIndirim are global variable which is defined in data property and it's obvious that if you change them, it applies to every iteration of your v-for block and not apply for each index separately.
In order to fix this, you can move addAciklama and addIndirim into each object in faturasections:
faturasections: [{
name: "",
unit_price: 0,
net_total: 0,
description: '',
discount_value: '',
addIndirim: false,
addAciklama: false,
}],
Then in your template section code, you should replace all addIndirim and addAciklama to fatura.addIndirim and fatura.addAciklama. this will fix your issue.
Picture of interlinkage between forms and fields.
I have searched this forum for an answer, as I suspect this has been asked before, but I haven't managed to find an answer.
I just picked up using Vue and Laravel, where I am building a form. Right now I am building a test to learn how to do it before I add complexity. The right form consists of 1 select-box and 3 text fields.
My requirements for the form are:
One button to duplicate the entire form.
One button in each form (also ones that are duplicated), which adds the 3 input-text fields in the form, by duplication the fields in the div called "registration_grid". One form may require the text-fields to be duplicated 10 times, others only 1 or 2...
I realize the code is a bit messy in its context, but it is put together by various pieces I found in tutorials along the way.
var app = new Vue({
el: '.container',
data: {
workouts: [
{
workout_unit: '',
workout_weight: '',
workout_comment: ''
}
]
},
methods: {
addNewEmployeeForm () {
this.workouts.push({
workout_unit: '',
workout_weight: '',
workout_comment: ''
})
},
deleteEmployeeForm (index) {
this.workouts.splice(index, 1)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<div class="container">
<button class="btn btn-primary" type="button" name="button" #click="addNewEmployeeForm">Add form fields</button>
<div class="card" v-for="(workout, index) in workouts">
<div class="card-body">
<i class="far fa-trash-alt float-right" #click="deleteEmployeeForm(index)"></i>
<h4 class="card-title">Test form - #{{index}}</h4>
<div class="employee-form">
<select class="form-select form-select-sm" aria-label=".form-select-sm example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<div class="registration_grid">
<input type="text" class="form-control" name="unit" placeholder="unit" v-model="workout.workout_unit">
<input type="text" class="form-control" name="weight" placeholder="weight" v-model="workout.workout_weight">
<input type="text" class="form-control" name="comment" placeholder="comment" v-model="workout.workout_comment">
</div>
</div>
</div>
</div>
Can this be done by Vue, and if so how?
You need to access the form data with workouts[index].unit for the v-model instead of workout.workout_unit
var app = new Vue({
el: '.container',
data: {
workouts: [
{
unit: '',
weight: '',
comment: ''
}
]
},
methods: {
addRow () {
this.workouts.push({
unit: '',
weight: '',
comment: ''
})
},
deleteRow (index) {
this.workouts.splice(index, 1)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<div class="container">
<button class="btn btn-primary" type="button" name="button" #click="addRow">Add form fields</button>
<div class="card" v-for="(workout, index) in workouts">
<div class="card-body">
<i class="far fa-trash-alt float-right" #click="deleteRow(index)"></i>
<h4 class="card-title">Test form - {{index}}</h4>
<div class="employee-form">
<select class="form-select form-select-sm" aria-label=".form-select-sm example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<div class="registration_grid">
<input type="text" class="form-control" name="unit" placeholder="unit" v-model="workouts[index].unit">
<input type="text" class="form-control" name="weight" placeholder="weight" v-model="workouts[index].weight">
<input type="text" class="form-control" name="comment" placeholder="comment" v-model="workouts[index].comment">
</div>
</div>
</div>
</div>
</div>
Modified example to only duplicate the input fields
var app = new Vue({
el: '.container',
data: {
workouts: [
{
unit: '',
weight: '',
comment: ''
}
]
},
methods: {
addRow () {
this.workouts.push({
unit: '',
weight: '',
comment: ''
})
},
deleteRow (index) {
this.workouts.splice(index, 1)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<div class="container">
<button class="btn btn-primary" type="button" name="button" #click="addRow">Add form fields</button>
<div class="card">
<div class="card-body">
<h4 class="card-title">Test form</h4>
<div class="employee-form">
<select class="form-select form-select-sm" aria-label=".form-select-sm example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<div class="registration_grid" v-for="(workout, index) in workouts">
<input type="text" class="form-control" name="unit" placeholder="unit" v-model="workouts[index].unit">
<input type="text" class="form-control" name="weight" placeholder="weight" v-model="workouts[index].weight">
<input type="text" class="form-control" name="comment" placeholder="comment" v-model="workouts[index].comment">
<i class="far fa-trash-alt float-right" #click="deleteRow(index)"></i>
</div>
</div>
</div>
</div>
</div>
I working on form which has nested form groups & form arrays but I am not able to bind values in ts.
I am new to angular so dont have much clarity on formgroup and form arrays.
below json can have multiple arrays within formgroups and nested form arrays within form group.
Here is the sample example which i want to execute and make below json structure from this form
Json using this form :
{
ip:'1.2.3.4',
create_adjacency:{
customerName:'ABC',
traffic_group:[{
_display_name:'DEF',
traffic_group_limits:{
calls:'23' }
}]
}
}
HTML -
<div class="page-container pb-25 ">
<form [formGroup]="firstFormGroup">
<div class="form-group custom-input select-custom-prime">
<label>IP</label>
<input
placeholder="Select"
formControlName="ip"
/>
</div>
<div class="row mb-20" formGroupName="create_adjacency">
<div class="col-xl-4 col-lg-6 col-md-6">
<div
class="form-group custom-input select-custom-prime"
>
<label>Customer Name</label>
<input
placeholder="Select"
formControlName="customerName"
/>
</div>
</div>
<div formArrayName="traffic_group">
<div class="col-xl-3 col-lg-6 col-md-6">
<div
class="form-group custom-input mr-10 select-custom-prime" >
<label>Traffic group Name</label>
<input
formControlName="_display_name"
/>
</div>
</div>
<table
class="mt-30 table table-striped table-bordered wd-98"
>
<thead>
<tr>
<th>Traffic Group Name</th>
<th>Concurrent Calls</th>
</tr>
</thead>
<tbody formGroupName="traffic_group_limits">
<tr>
<td>
<div class="">
<div
class="form-group custom-input select-custom-prime"
>
<input
pInputText
autofocus
disabled
type="text"
class="form-control"
/>
</div>
</div>
</td>
<td>
<div class="">
<div
class="form-group custom-input select-custom-prime"
>
<input
formControlName="calls"
pInputText
autofocus
class="form-control"
/>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</form>
</div>
Ts code -
this.firstFormGroup = this.formBuilder.group({
ip: [''],
create_adjacency: this.formBuilder.group({
customerName: ["", Validators.required],
traffic_groups: this.formBuilder.array([this.traffic_groups])
})
});
get traffic_groups(): FormGroup {
return this.formBuilder.group({
_display_name: ["", Validators.required],
traffic_group_limits: this.formBuilder.group({
"call-appearances": ["", Validators.required]
})
});
}
In my opinion, as much angular has their own way of doing this, it might be a little intimidating to a beginner. So I prefer breaking down the formgroups and then constructing the final json from all the forms all together.
.html
<div class="page-container pb-25 ">
<form [formGroup]="firstFormGroup">
<div class="form-group custom-input select-custom-prime">
<label>IP</label>
<input
placeholder="Select"
formControlName="ip"
/>
</div>
<div class="row mb-20" [formGroup]="adjacencyFormGroup">
<div class="col-xl-4 col-lg-6 col-md-6">
<div
class="form-group custom-input select-custom-prime"
>
<label>Customer Name</label>
<input
placeholder="Select"
formControlName="customerName"
/>
</div>
</div>
<div [formGroup]="trafficFormGroup">
<div class="col-xl-3 col-lg-6 col-md-6">
<div
class="form-group custom-input mr-10 select-custom-prime" >
<label>Traffic group Name</label>
<input
formControlName="_display_name"
/>
</div>
</div>
<table
class="mt-30 table table-striped table-bordered wd-98"
>
<thead>
<tr>
<th>Traffic Group Name</th>
<th>Concurrent Calls</th>
</tr>
</thead>
<tbody [formGroup]="trafficGroupLimit">
<tr>
<td>
<div class="">
<div
class="form-group custom-input select-custom-prime"
>
<input
pInputText
autofocus
disabled
type="text"
class="form-control"
/>
</div>
</div>
</td>
<td>
<div class="">
<div
class="form-group custom-input select-custom-prime"
>
<input
formControlName="calls"
pInputText
autofocus
class="form-control"
/>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</form>
</div>
.ts
this.firstFormGroup = this.formBuilder.group({
ip: [''],
create_adjacency: [{}]
});
this.adjacencyFormGroup = this.formBuilder.group({
customerName: ["", Validators.required],
traffic_groups: [[]])
});
this.trafficFormGroup = this.formBuilder.group({
_display_name: ["", Validators.required],
traffic_group_limits: [{}]
});
this.trafficGroupLimit = this.formBuilder.group({
calls: [''],
});
function to create json
createFormJSON() {
this.trafficFormGroup.patchValue({
traffic_group_limits: this.trafficGroupLimit.value
});
this.adjacencyFormGroup.patchValue({
traffic_groups: this.allTrafficGroups // store all traffic groups in this array before patching
});
this.firstFormGroup.patchValue({
create_adjacency: this.adjacencyFormGroup.value,
});
}
I have a VueJS component which populates a table via ajax, than I have a modal form inside component which creates new entries in table.
On modal hide I want to update the table to show new entries.
export default {
created() {
axios.get('/api/v1/customers')
.then(response => {
this.customers = response.data;
});
},
methods: {
store() {
this.form.errors = [];
axios.post('/api/v1/customers', this.form)
.then(response => {
this.form.name = '';
this.form.scopes = [];
this.form.errors = [];
$('#modal-edit-client').modal('hide');
this.$forceUpdate();
})
.catch(error => {
console.log(error)
/*if (typeof error.response.data === 'object') {
this.form.errors = _.flatten(_.toArray(error.response.data));
} else {
this.form.errors = ['Something went wrong. Please try again.'];
}*/
});
},
newUser: function () {
$('#modal-edit-client').modal('show');
},
edit: function () {
alert('edit modal')
}
},
data() {
return {
customers: {},
alert: {
show: false,
type: null,
title: null,
message: null,
},
form: {
scopes: [],
errors: []
}
};
}
}
I tried to use $forceUpdate() but does not seems to work
output template
<template>
<div class="row" v-cloak>
<div class="col-md-12 ">
<div class="panel panel-default custom-panel">
<div class="panel-heading">
<strong>Customers</strong>
<div id="custom-search-input">
<div class="input-group col-md-12">
<input v-on:keyup.enter="filter" type="text" class="form-control input-sm" placeholder="Search Customer" />
<span class="input-group-btn">
<button class="btn btn-info btn-lg" type="button">
<i class="glyphicon glyphicon-search"></i>
</button>
</span>
</div>
</div>
<a class="btn icon-btn btn-success" id="new__item" href="#" #click="newUser">
<span class="glyphicon btn-glyphicon glyphicon-plus img-circle text-success"></span> Add Customer
</a>
</div>
<div class="panel-body">
<table class="table table-condensed">
<tbody>
<tr>
<th style="width: 10px">#</th>
<th>Firma</th>
<th>Strasse</th>
<th>PLZ</th>
<th>Ort</th>
<th>Tel</th>
<th>Status</th>
<th>Actions</th>
</tr>
<tr v-for="customer in customers">
<td>{{ customer.id }}</td>
<td>{{ customer.customer_name }}</td>
<td>{{ customer.customer_street }}</td>
<td>{{ customer.customer_plz }}</td>
<td>{{ customer.customer_city }}</td>
<td>{{ customer.customer_telephone }}</td>
<td><span class="badge bg-green"><i class="fa fa-check"></i></span></td>
<td class="actions">
<i class="fa fa-pencil"></i>
<i class="fa fa-trash"></i>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- Edit Client Modal -->
<div class="modal fade" id="modal-edit-client" tabindex="-1" role="dialog">
<div class="spinner"></div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button " class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">
Add Customer
</h4>
</div>
<div class="modal-body">
<!-- Form Errors -->
<!--<div class="alert alert-danger" v-if="alert" >
<p><strong>Whoops!</strong> Something went wrong!</p>
<br>
</div>-->
<!-- Edit Client Form -->
<form class="form-horizontal" id="modal-create-customer" role="form" method="POST" action="">
<div class="row">
<div class="col-xs-12">
<label for="customer_name" class="control-label">Firmenbezeichnung</label>
<input id="customer_name" type="text" class="form-control" v-model="form.customer_name" name="customer_name" value="" required autofocus>
<span class="help-block">
<strong></strong>
</span>
</div>
<div class="col-xs-6">
<label for="sex" class="control-label">Anrede</label>
<select v-model="form.customer_contact_sex" name="title" id="sex" class="form-control">
<option value="Herr">Herr</option>
<option value="Frau">Frau</option>
</select>
<span class="help-block">
<strong></strong>
</span>
</div>
<div class="col-xs-6">
<label for="title" class="control-label">Title</label>
<select v-model="form.customer_contact_title" name="title" id="title" class="form-control">
<option value="">No title</option>
<option value="Dr.">Dr.</option>
<option value="Prof.">Prof.</option>
</select>
<span class="help-block">
<strong></strong>
</span>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<label for="name" class="control-label">First Name</label>
<input id="name" type="text" class="form-control" v-model="form.customer_first_name" name="customer_name" value="" required autofocus>
<span class="help-block">
<strong></strong>
</span>
</div>
<div class="col-xs-6">
<label for="email" class="control-label">Last Name</label>
<input id="email" type="text" class="form-control" v-model="form.customer_last_name" name="customer_last_name" value="" required>
<span class="help-block">
<strong></strong>
</span>
</div>
<div class="col-xs-6">
<label for="street" class="control-label">Street</label>
<input id="street" type="text" class="form-control" v-model="form.customer_street" name="customer_street" value="" required>
<span class="help-block">
<strong></strong>
</span>
</div>
<div class="col-xs-2">
<label for="plz" class="control-label">PLZ</label>
<input id="plz" type="text" class="form-control" v-model="form.customer_plz" name="customer_plz" value="" required>
<span class="help-block">
<strong></strong>
</span>
</div>
<div class="col-xs-4">
<label for="city" class="control-label">City</label>
<input id="city" type="text" class="form-control" v-model="form.customer_city" name="customer_city" value="" required>
<span class="help-block">
<strong></strong>
</span>
</div>
<div class="col-xs-6">
<label for="customer_telephone" class="control-label">Tel.</label>
<input id="customer_telephone" type="text" class="form-control" v-model="form.customer_telephone" name="customer_telephone" value="" required>
<span class="help-block">
<strong></strong>
</span>
</div>
<div class="col-xs-6">
<label for="customer_fax" class="control-label">Fax.</label>
<input id="customer_fax" type="text" class="form-control" name="customer_fax" value="" required>
<span class="help-block">
<strong></strong>
</span>
</div>
<div class="col-xs-6">
<label for="customer_mobile" class="control-label">Mobil</label>
<input id="customer_mobile" type="text" class="form-control" name="customer_mobile" value="" required>
<span class="help-block">
<strong></strong>
</span>
</div>
<div class="col-xs-6">
<label for="customer_email" class="control-label">E-Mail.</label>
<input id="customer_email" type="text" class="form-control" name="customer_email" value="" required>
<span class="help-block">
<strong></strong>
</span>
</div>
<div class="col-xs-12">
<label for="customer_note" class="control-label">Notiz</label>
<textarea name="csutomer_note" id="customer_note" class="form-control"></textarea>
<span class="help-block">
<strong></strong>
</span>
</div>
</div>
</form>
</div>
<!-- Modal Actions -->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" #click="store">
Register
</button>
</div>
</div>
</div>
</div>
</div>
</template>
As said in the comments, your code looks fine except that you're not actually updating the customers property with anything.
When you're performing the XHR request with Axios, you need to use the response to populate the component, which will automatically update the relevant DOM.
Here is the relevant part of your code that you should modify:
axios.post('/api/v1/customers', this.form)
.then(response => {
this.form.name = '';
this.form.scopes = [];
this.form.errors = [];
// Set the component's customers property to what you get
// in the response
this.customers = response.data.customers;
$('#modal-edit-client').modal('hide');
// You don't need to forceUpdate as Vue will take care of
// rerendering the relevant parts of the DOM
// this.$forceUpdate();
})
Also, considering you're expecting an array of customers to render the table, you should set the customers default value accordingly:
data() {
return {
customers: []
// ...
};
}