Reputation: 3377
I have a v-for rendered table that has products in it. This table has a column for "active" status where i want the user to be able to click the active button and it becomes inactive or click the inactive button and it becomes active (a toggle switch basically).
I have this implemented by making a POST call to an api route where my status is updated. This works fine.
The problem is that I cannot get vueJS to update the affected object in the array more than once. this.$set works ONE time. If I hit the toggle switch a second time, it no longer works.
This is my table:
<table class="table table-striped fancy-table">
<thead>
<tr>
<th class="text-center"> </th>
<th>Product/Service</th>
<th class="text-center">Status</th>
<th class="text-center">Date Added</th>
<th class="text-center">QTY Sold</th>
<th class="text-center"> </th>
</tr>
</thead>
<tbody>
<tr v-for="(service, index) in services">
<td class="text-center">
<img v-if="service.featured_image" :src="service.featured_image" class="table-thumb">
<img v-else src="/img/default-product.png" class="table-thumb">
</td>
<td>{{service.service_name}}<span class="secondary">${{parseFloat(service.price).toFixed(2)}}</span></td>
<td class="text-center">
<a href="#" v-if="service.active === 1" @click.prevent="updateStatus(service, index, 0)"><i class="fas fa-circle active"></i></a>
<a href="#" v-else="service.active === 0" @click.prevent="updateStatus(service, index, 1)"><i class="fas fa-circle inactive"></i></a>
</td>
<td class="text-center">{{ service.created_at | moment("dddd, MMMM Do YYYY") }}</td>
<td class="text-center">10</td>
<td class="text-center"><a href="#"><i class="fal fa-edit table-action-btn"></i></a></td>
</tr>
</tbody>
</table>
This is my method controlling the update:
updateStatus: function(service, index, status) {
// Grab the authorized user
const authUser = JSON.parse(window.localStorage.getItem('authUser'))
// Add a role and refresh the list
this.$http.post('/api/vendor/services/update/' + service.id + '?updateActive=' + status, { }, { headers: { Authorization: 'Bearer ' + authUser.access_token } }).then((response) => {
// update this service
this.$set(this.services, index, response.body);
}).catch(function(error){
console.log(error);
})
}
EDITS:
I've added a :key param to the v-for table, but I'm still getting the same issue. As you can see in my network panel, the first time you click the button, it goes as expected. Posts to the api route with updateActive=0. The second time you click the button it posts to the api route with updateActive=1 and the data is changed server side, but at this point, my object in the services array is not updated, so it now just continually posts with updateActive=1 rather than showing my other button (toggle switch like i'm wanting).
Here's a screenshot of my network panel with 4 clicks on the button.
Upvotes: 1
Views: 4868
Reputation: 3377
Thanks to @Daniel above, the answer was that I was expecting a number value back (as it is set to an integer in MySQL) and my ajax call was returning that field as a string.
Upvotes: 0
Reputation: 35704
The problem here might be with a missing key
in your v-for
<tr v-for="(service, index) in services">
you could use the key from the index, but in some occasions that may also cause an issue (for example, when removing a single item in an array, the last DOM object will be removed, because the keys shift over)
<tr v-for="(service, index) in services" :key="index">
Ideally you could use something unique from the data like
<tr v-for="(service, index) in services" :key="service.id">
Upvotes: 2