Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Vuetify Data table not updating correctly?

So I'm populating the data table with items fetched via API and it is working fine, but if I want to edit any of the fields it's not quite working out.

The item only updates if I manually do something like search or sort. (inside the data table)

The fields I'm trying to modify are item.tuning and item.url via getTab()

<v-data-table 
class="tableElem"
:headers="headers"
:items="playlist"
:loading="loadingPlaylist"
:search="search"
:pagination.sync="pagination"
:rows-per-page-items="[15]"
hide-actions
>
<v-progress-linear slot="progress" color="purple" indeterminate></v-progress-linear>
<template slot="items" slot-scope="props">
  <td>{{ props.item.artist }}</td>
  <td class="text-xs-right">{{ props.item.track }}</td>
  <td class="text-xs-right">{{ props.item.tuning | tuning }}</td>
  <td class="text-xs-right">
    <v-btn 
    v-if="props.item.url" 
    depressed outline light 
    style="margin-top:1rem;margin-bottom:1rem;" 
    :href="props.item.url" 
    target="!blank">
      Tab
    </v-btn>
    <div class="text-xs-center" v-else-if="props.item.url == false">No tab :(</div>
    <v-btn 
    v-else 
    depressed outline light 
    style="margin-top:1rem;margin-bottom:1rem;" 
    v-on:click="getTab(props.item.artist, props.item.track, props.item)">
      Get Tab
    </v-btn>
  </td>
</template>
<v-alert slot="no-results" :value="true" style="color:black;" icon="warning">
  Your search for "{{ search }}" found no results.
</v-alert>
</v-data-table>

methods:

getTab(artist, track, item) {
  //const tabURL = "https://stark-beyond-77127.herokuapp.com/spotify/gettab";
  let itemIndex = this.playlist.indexOf(item)
  const tabURL = "http://localhost:5000/spotify/gettab";
  const tabJSON = {
    artist: artist,
    track: track
  };
  axios.post(tabURL, tabJSON).then(response => {
    let tuning = response.data[0].tuning;
    let url = response.data[0].url;
    this.playlist[itemIndex] = { ...this.playlist[itemIndex], ...{ tuning: tuning, url: url } };
    console.log(this.playlist[itemIndex]);
  });
}

My guess here is that I'd have to use computed: or watch: but dont know how to implement that. Thanks

like image 218
breke Avatar asked Oct 02 '18 17:10

breke


4 Answers

let itemIndex = this.playlist.indexOf(item)
let editedItem = { ...this.playlist[itemIndex], ...{ tuning: tuning, url: url } };
this.playlist.splice(itemIndex, 1, editedItem)

Fixes the problem. I'd guess splice forces a dom refresh that directly editing array didn't.

like image 171
breke Avatar answered Oct 10 '22 10:10

breke


If anyone facing this problem too, I would like to share my solution.

The solution is declare the attribute to null before adding new attribute to JSON array.

In OP case,

const tabJSON = {
    artist: artist,
    track: track
    tuning: null,
    url: null
};

This is my problem, the added attribute to array of json object does not show unless sort button is clicked.

problem gif

In my case, I need to retrieve data from firestore and add in attributes into array.

db.collection("checkout")
  .get()
  .then(querySnapshot => {
    querySnapshot.forEach(doc => {
      const data = {

        book_did: doc.data().book_did,
        borrowed_date: doc.data().borrowed_date.toDate(),
        due_date: doc.data().due_date.toDate(),

        book_title: null, // solution
        returned_date: null, // solution
        days_late: null // solution
      };
      this.checkout.push(data);
    });

    // modified this.checkout array here:
    Object.keys(this.checkout).forEach(key => {
      db.collection("books")
        .doc(this.checkout[key].book_did)
        .get()
        .then(snapshot => {
          this.checkout[key].book_title = snapshot.data().title;
        });
    });
  });
like image 45
wei Avatar answered Oct 10 '22 11:10

wei


In my case, unexpected behaviour comes from the v-for key. My data are not using "id" as the key. After I re-read the docs, I realized that Vuetify is using "id" as the default key for the items.

The solution is I have to specify the item-key props for the v-data-table so that it behaves as expected.

Example:

data: () => ({
  playlist: [
    { key: 1, name: 'Foo' },
    { key: 2, name: 'Bar' },
  ],
}),

Use item-key:

<v-data-table :headers="headers" :items="playlist" item-key="key">
like image 1
Mgs M Rizqi Fadhlurrahman Avatar answered Oct 10 '22 09:10

Mgs M Rizqi Fadhlurrahman


Vue cannot pick up the change in array when you directly set the index or changing the length.

See article: Update Array and Object in Vuejs.

Instead you can use:

Vue.set(vm.items, indexOfItem, newValue)

vm.items.splice(indexOfItem, 1, newValue) 
like image 1
Chris Herbst Avatar answered Oct 10 '22 11:10

Chris Herbst