2
votes

I'm a Vue.js and Vuetify newbie so please be gentle ;-)

I'm using Vue.js with Vuetify's data table and on each row I have a button that calls a method which does something. My problem is that using the ':disabled="props.item.isRefreshing"' on each row doesn't seem to respect if I change the value of 'isRefreshing' on that particular row.

So here's my data table, with 'rows' being the collection of my models each with an 'isRefreshing' property. If I change the value of any particular row in the code then the corresponding row button should be disabled, but in the 'refreshExtract()' method this has no effect whether I use the passed in 'row' (i.e. the row.item parameter) or if I actually change the value in the 'rows' list property directly in the 'refreshExtract()' method.

Is this expected behaviour, a bug in Vuetify or am I misunderstanding how to use Vue.js or Vuetify? I think I basically after someway of getting the 'isRefreshing' on each row to be 'watched' and to change the disabled state of the button on the corresponding row.

Either way, what would be the best/simplest method for acheiving what I'm after?

    <v-data-table v-model="selectedRows"                      
                  v-bind:headers="headers"
                  v-bind:items="rows"
                  v-bind:loading="loading"
                  v-bind:pagination.sync="pagination"
                  v-bind:total-items="totalRows"                      
                  class="elevation-1">
        <template slot="items" slot-scope="row">
            <td>
                {{ row.item.name }}
            </td>
            <td>
                {{ formatDate(row.item.lastRefreshedAt) }}
            </td>
            <td>
                <v-btn v-if="row.item.isExtract" 
                       :disabled="row.item.isRefreshing"                                                      
                       color="primary"
                       @click="refreshExtract(row.item)">
                    Refresh Extract
                </v-btn>
            </td>
        </template>
    </v-data-table>

I can of course change the button to be disabled by changing the @click to '@click="row.item.isRefreshing = true;refreshExtract(row.item)"' but that seems a little ugly and besides I need to programmatically re-enable the button once the refresh completes...

UPDATE

Be aware that I'm using TypeScript here, so as per the comments the 'rows' property:-

public rows: DataSource[]

is an array of data source models of which:-

export default class DataSource {
    public description: string;
    public id: number;
    public isExtract: boolean;
    public isRefreshing: boolean;
    public lastRefreshedAt: Date;
    public name: string;
    public projectId: number;
}

The methods in my component are as follows. Note that I've tried to directly update the rows property with the enable/disable methods to see if that worked which it didn't:-

    protected disableDataSourceRefresh(dataSource: DataSource): void {
        for (let i = 0; i < this.rows.length; i++) {
            if (this.rows[i].id == dataSource.id) {
                this.rows[i].isRefreshing = true;
            }
        }
    }

    protected enableDataSourceRefresh(dataSource: DataSource): void {
        for (let i = 0; i < this.rows.length; i++) {
            if (this.rows[i].id == dataSource.id) {
                this.rows[i].isRefreshing = false;
            }
        }
    }

    public refreshExtract(dataSource: DataSource): void {        
        if (dataSource.isExtract) {
            if (dataSource.isRefreshing) {
                alert('Data is currently refreshing');
            } else {
                this.disableDataSourceRefresh(dataSource);

                axios.post(*** removed ***)
                    .then(response => {
                        alert("done");

                        this.enableDataSourceRefresh(dataSource);
                    })
                    .catch(error => {
                        console.log(error);
                    });
            }
        }
    }

Originally the refreshExtract() method just was as below, but I wasn't expecting that updating 'dataSource' would filter back down to the original item that was passed, but figured give it a go anyway as this could be something wild cool thing that Vue.js does! ;-)

    public refreshExtract(dataSource: DataSource): void {        
            if (dataSource.isExtract) {
                if (dataSource.isRefreshing) {
                    alert('Data is currently refreshing');
                } else {
                    dataSource.isRefreshing = true;

                    axios.post(*** removed ***)
                        .then(response => {
                            alert("done");

                            dataSource.isRefreshing = false;
                        })
                        .catch(error => {
                            console.log(error);
                        });
                }
            }
        }
1
It looks absolutly fine for me. Can you track what your problem is? For example is isRefreshing in the right scope and gets changed?Thomas
What does the rows data item look like? How does it get its values?Roy J
Thomas - please could you explain further when you say 'right scope'? Roy - I've added them to the post...padigan
Where do you get the rows from? I guess, that you get all as a array and then use them? Try to do: Vue.set() with the array so all data gets responsive.Thomas
@ThomasKleßen - bingo! that worked, in the enable/disable methods I changed the 'this.rows[i].isRefreshing = true;' to 'Vue.set(this.rows[i], 'isRefreshing', true);' and vice-versa for the other method! Thankyou, I'll need to remember that one ;-) If you can post an answer I'll mark it as the correct answer for this question so you can get the points ;-)padigan

1 Answers

3
votes

If you are using an array of Objects with Vue then the properties in the Objects are not responsive by default.

Thats why your changes to isRefreshing are not mirrowed into your view.

To prevent that behavior you must use Vue.set(myArray, myIndex, newObject) methode and everything should work as expected.