2

I want to create a reactive Datatable in my Laravel + Vue.js project. I'm using datatables.js library to show my data. When I make an API call to get the data from db API returns me an array, so I want to populate that array in the datatable. But it's working weird?

Here's API call:

methods: {
    getUsers() {
        axios.get('/api/users')
            .then(response => {
                if(response.status === 200) {
                    this.users = response.data.users;
                    console.log(this.users);
                }
            })
            .catch(error => {
                console.error(error);
            });
    }
},
mounted() {                
    $('#users-datatable-responsive').DataTable();
    this.getUsers();
}

This is how I populating the data in the datatable

<tr v-for="user in users">
    <td>@{{ user.fullname }}</td>
    <td>@{{ user.phone }}</td>
    <td>@{{ user.email }}</td>
</tr>

And here's the weird result: enter image description here

Searching and other features of a datatable aren't working. What's the workaround?

Edited:

mounted() {               
    let table = $('#users-datatable-responsive').DataTable({
        language: this.dataTableOptions
    });
    this.getUsers();
    table.rows().invalidate().draw();
}

This approach didn't work for me.

8
  • 1
    That's because DataTables plugin does not automatically detect changes in DOM and updates its internal mapping of your data. You should force the instance to refresh, by invalidating the data and redrawing it, i.e. table.rows().invalidate().draw(); Commented Apr 2, 2018 at 11:01
  • Possible duplicate of How do I refresh/reload my DataTable from HTML source Commented Apr 2, 2018 at 11:01
  • @Terry please look at my editings. Commented Apr 2, 2018 at 11:07
  • @Terry this approach didn't work for me Commented Apr 2, 2018 at 11:07
  • Probably because you are refreshing the table before axios actually successfully fetches the data and updates Vue's data store, since axios' operations are asynchronous. Commented Apr 2, 2018 at 11:13

3 Answers 3

1

I was unable to get Terry's answer to work, but after a little bit of playing around found that that destroying the table before render, then rebuilding the table on the next tick does work.

...
methods: {
        drawDT() {
          $("#dt").DataTable().draw();
        },
        async refreshData() {
          this.isLoading = true;
          $("#dt").DataTable().destroy();
          try {
            let data = await fetchData();
            this.users = data.slice(0, getRandomInt(1, data.length));
            await this.$nextTick(this.drawDT);
          } catch (err) {
            console.error(err);
          } finally {
            this.isLoading = false;
          }
        }
      },
...

Full example here

Sign up to request clarification or add additional context in comments.

2 Comments

It gets me the same effect as Terry's (((
Sorry to hear that. As you can see, my example is working, so hopefully it's of some help you. Otherwise can you post your code somewhere so others can hopefully spot the problem?
0

If it is a simple table you could use this grid table component from vue docs https://v2.vuejs.org/v2/examples/grid-component.html

Comments

0

As per my comments, there are two issues that are causing the problem you are seeing:

  1. DataTable plugin does not automatically updates its internal cache when you update the DOM. You will need to use its API to 'reset' the table, i.e. table.rows().invalidate().draw();
  2. Axios works asynchronously, and you should reset the table only when the promise has been resolved. This should ideally be done using a custom method to keep things abstract :)
  • In your custom method, you must wait for VueJS to finish updating the DOM, since the DOM relies on iterating through this.users to render the correct markup. Use Vue.nextTick() to call the logic that 'resets' the table.

To fix this, you can call a custom method in your app/component that handles forced refreshing of the table, i.e.:

methods: {
    getUsers() {
        axios.get('/api/users')
            .then(response => {
                if(response.status === 200) {
                    // Populate VueJS data store with received data
                    this.users = response.data.users;

                    // Call a method that manually refreshes table
                    this.forceRefreshUserDataTable();
                }
            })
            .catch(error => {
                console.error(error);
            });
    }
},
mounted() {             
    this.usersDataTable = $('#users-datatable-responsive').DataTable();
    this.getUsers();
},
methods: {
    forceRefreshUserDataTable() {
        Vue.nextTick(function () {
            this.usersDataTable.rows().invalidate().draw();
        });
    }
}

4 Comments

Error in nextTick: "TypeError: $(...).rows is not a function". This's the result.
@КамиловТимур Whoops, my bad. You can either choose to store the instantiated DataTable object (i.e. this.usersDataTable = ...), or chain .DataTable() to access the API, i.e. $('#users-datatable-responsive').DataTable().rows().invalidate().draw()
Which type does usersDataTable has? Cz ur code doesn't still work ((
after the nextTick() datatable is being truncated, right? And now, how to repopulate the users array to the datatable?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.