[SOLVED] Table component not updating when data added dynamically



  • I have a table definition with two columns, and the second column’s data for each cell requires a separate API call. Adding the data to my data array does not result in the data showing up in the table. Is there something special I need to do besides modifying the data array? My array and defs prior to adding look like this:

    data () {
        return {
          columns: [
            { name: 'first', align: 'left', label: 'first', field: 'first', sortable: true },
            { name: 'second', align: 'center', label: 'second', field: 'second', sortable: true }
          ],
         colData: [
                 {
                   first: 'some val',
                   second: ''
                 },
                {
                   first: 'some other val',
                   second: ''
                 }
          ]
       }
    }
    

    And after I have run my lookups, the colData object is changed to look like the following:

    colData: [
                 {
                   first: 'some val',
                   second: 'second val'
                 },
                {
                   first: 'some other val',
                   second: 'second other val'
                 }
          ]
    

    I have verified that the data is there by inspecting the object in devtools, but the table does not update to show the added values.



  • I’ve tried returning the data in a computed property, and still no luck. I’m really at a loss here. Is this a bug or limitation of the table component in quasar?



  • @ssuess your colData is what you pass to data prop of QTable? probably need a reproduction.



  • yes sorry here is my table def:

    <q-table
          :data="colData"
          :columns="columns"
          row-key="name"
          :filter="filter"
          :loading="loading"
          dense
        ><template v-slot:body="props">
            <q-tr :props="props">
              <q-td key="first" :props="props">
                <span class="link" @click="setSearch(props.row.first)">{{ props.row.first }}</span>
              </q-td>
              <q-td key="second" :props="props">
             <div v-if="props.row.second === ''">
              <q-spinner color="primary" size="1.5em" />
             </div>
             <div v-else>something </div>
              </q-td>
              </q-tr>
              </template><template v-slot:top-right>
            <q-input borderless dense debounce="300" v-model="filter" placeholder="Search">
              <template v-slot:append>
                <q-icon name="search" />
              </template>
            </q-input>
          </template>
          </q-table>
    

    The spinners show up and never go away, since they never seem to know that the values in the data object have changed, even though in the devtools they have updated.



  • @ssuess need to see your function that changes the colData. If its an api call then you need to set loading to false at your finally callback or if you use try catch finally blocks etc.



  • I have tried both with using loading and not using loading (following the addRow script example on this page: https://quasar.dev/vue-components/table and trying with the same type of timeout call), it makes no difference at all. (and as far as I can tell, adding this.loading = true and then this.loading =false only adds an animation to the top of the table) Also like I said, when I use devtools to inspect, my object is indeed properly updated with the correct structure. It is simply that the table component does not reflect the changes to the data. When I get into the office tomorrow I will post my method that makes the axios call and updates the object. Thanks for your help, I appreciate it.



  • @ssuess i’m using q-table extensively and can confirm that everything you have mentioned does work for me. you should provide a barebone reproduction, so we can see what’s wrong.



  • @metalsadman Here is a full working example that demonstrates my problem, using the real APIs and some real data: https://codepen.io/ssuess/pen/LYEOWNZ

    I have set timeouts to display in the console the data object before and after data is added. You can see that the spinners never go away, despite the object being updated. If you can figure out why that is the case, I would be very happy as I am stumped at the moment. Thanks!

    btw, if you use the search filter after the data has loaded, or sort the data by col header, it WILL redraw the table and update the values. But it will not do it on simply updating the data object.



  • This is not a problem with QTable, but with Vue’s reactivity system.
    Its a common pitfall and thankfully this will be improved when Vue 3.0 comes out (I think).

    You can read about it here: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

    The example in the link deals with exactly your problem: You initialize your objects in this.prefixes as objects having the properties timelines and prefix, so they are reactive automatically (that is Vue sets up it’s change-detection-system for them).
    Then you assign a new property rpki using this.prefixes[key].rpki = '1' – this is not reactive in Vue 2.x !! So when you change that property later, Vue doesn’t notice it.

    One way to solve your problem is by explicitly telling Vue that your objects have a new property. For this, Vue provides an alternative way of assigning values to object properties:

    In refreshAPwidget(), replace

    this.prefixes[key].rpki = '1'
    

    with:

    this.$set(this.prefixes[key], 'rpki', '1')
    

    On a similar note, it is better to write this.$delete(this.prefixes[key], 'timelines') instead of delete this.prefixes[key].timelines, but this doesn’t affect your example.



  • @chyde90 WOW. Thanks!! I don’t think I ever would have figured that out.

    I suppose another option would have been to assign a new property inside an object var inside my axios response, and THEN initialize the object to this.prefixes



  • @ssuess quite late, @chyde90 got you covered and should always take heed about what he has pointed out, anyway here without using Vue.set https://codepen.io/metalsadman/pen/vYEpKdY. you didn’t need to assign the result first to your local data, if you were going to re-shape the result anyway.


Log in to reply