简体   繁体   中英

Vue JS this.$set not updating reactivity

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">&nbsp;</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">&nbsp;</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.

在此处输入图片说明

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">

感谢上面的@Daniel,答案是我期望返回一个数字值(因为在MySQL中将其设置为整数),而我的ajax调用将该字段作为字符串返回。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM