Reputation: 1381
I'm stuck on a problem and was hoping that a Javascript Jedi could help point me in the right direction.
Scope of the problem:
I'm passing a Laravel collection to my Vue component. Inside the component, I'm iterating through the collection and submitting a form via axios. The form submits, the data is updated in the database, but __I'm not clear on how to show the updated value without a page refresh.__
Expected Outcome:
The updated data is reflected in the {{ collection.value }}
inside the Vue template after form submission
What's going wrong:
The data is being updated in the database, but the {{ collection.value }}
remains the same until page is reloaded.
Web.php:
Route::post('/updateQty', 'MyController@update');
MyController:
public function update(Request $request)
{
$product = Product::where('id', $request->productId)
->update([ 'qty' => $request->qty ]);
return response()->json($product);
}
public function index()
{
$collection = DB::table('products')->get();
return view('my-blade', [
'collections' => $collection,
]);
}
Structure of $collection as stored in the database:
'qty' => decimal(8,2),
'class' => varchar(255),
'description' => varchar(255),
'value' => decimal(8,2),
'productId' => int(11)
my-blade:
<my-component :collections="{{ $collections }}"></my-component>
MyComponent.vue:
<template>
<div class="container">
<div class="row">
<div class="col-lg-12">
<table class="table table-sm">
<div v-if="collections.length">
<tr v-for="collection in collections" v-bind:key="collection.id">
<td>
<form @submit="updateQty">
<input type="hidden" id="productId" :value="collection.productId" name="productId">
<select class="form-control" name="qty" id="qty" @change="updateQty">
<option :value="collection.qty">{{ collection.qty }}</option>
<option v-for="(x, index) in 200" v-bind:key="index" :value="index">{{ index }}</option>
</select>
</form>
</td>
<td>{{ collection.value }}</td>
</tr>
</div>
</table>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['collections'],
data() {
return {
qty: '',
}
}
mounted() {
console.log('MyComponent.vue mounted successfully');
},
methods: {
updateQty(e) {
e.preventDefault();
let currentObj = this;
let url = '/updateQty';
axios.post(url, {
qty: qty.value,
})
.then(function (response) {
currentObj.value = (response.data);
let collections = response.data;
})
},
}
}
</script>
App.js
Vue.component('my-component', require('./components/MyComponent.vue'));
I'm sure it's something simple, but for the life of me I can't wrap my head around it. Thank you very much in advance!
Upvotes: 4
Views: 5230
Reputation: 5149
You just need to change up your script a bit.
First, save the collections property to a data property, or Vue will scream when you try to update it. To do this, I would rename the incoming prop
as something like collections_prop
. Then save it to the collections
data property.
Then change let collections =
to this.collections =
in your update response.
EDIT: I changed the .then
function to ES6 syntax as you may have trouble accessing the this
variable otherwise. No need for the currentObj
stuff.
export default {
props: ['collections_prop'],
mounted() {
console.log('MyComponent.vue mounted successfully');
},
data() {
return {
collections: this.collections_prop;
}
},
methods: {
updateQty(e) {
e.preventDefault();
let url = '/updateQty';
// not sure where qty is coming from
// but you said that's all worked out
// on your end
axios.post(url, {
qty: qty.value,
})
.then(response => {
this.collections = response.data;
})
},
}
}
And finally, don't forget to update the prop in your view.
<my-component :collections_prop="{{ $collections }}"></my-component>
Or if you want to later specify prop type as JSON:
<my-component :collections_prop='@json($collections)'></my-component>
Upvotes: 4