Vuejs and datatables: table empty when using v-for

2019-08-04 23:44发布

问题:

I'm trying to fill a datatable using vuejs v-for directive and ajax to get the data but the table is always showing "No data available in table" even though there are some data shown and also in the bottom says "Showing 0 to 0 of 0 entries". I guess this is because vuejs is reactive and the table can't recognize the changes maybe? I've been searching and trying for a while but with no solution found..

thanks a lot! :)

here's the template:

<div class="row">
    <div class="col-sm-12">
        <div class="box box-color box-bordered">
            <div class="box-title">
                <h3>
                    <i class="fa fa-table"></i>

                </h3>
            </div>
            <div class="box-content nopadding">
                <table id="suppliersTable" class="table table-hover table-nomargin table-bordered dataTable">
                    <thead>
                        <tr>
                            <th>Supplier #</th>
                            <th>Company</th>
                            <th class='hidden-1024'>Email</th>
                            <th class='hidden-480'>Phone</th>
                            <th class='hidden-480'>Fax</th>
                            <th class='hidden-480'>Mobile</th>
                            <th class='hidden-480'>City</th>
                            <th class='hidden-480'>Street</th>
                            <th class='hidden-480'>Postal Code</th>
                            <th class='hidden-480'>CR</th>
                            <th class='hidden-480'>Website</th>
                            <th class='hidden-480'>Notes</th>
                        </tr>
                    </thead>
                    <tbody>                            
                        <tr class="template" v-for="supplier in suppliers">
                            <td class='verticalAlignMiddle'>{{ supplier.Supplier_ID }}</td>
                            <td class='verticalAlignMiddle'>{{ supplier.Company }}</td>
                            <td class='verticalAlignMiddle hidden-1024'>{{ supplier.Email }}</td>
                            <td class='verticalAlignMiddle hidden-480'>{{ supplier.Phone }}</td>
                            <td class='verticalAlignMiddle hidden-480'>{{ supplier.Fax }}</td>
                            <td class='verticalAlignMiddle hidden-480'>{{ supplier.Mobile }}</td>
                            <td class='verticalAlignMiddle hidden-480'>{{ supplier.City_ID }}</td>
                            <td class='verticalAlignMiddle hidden-480'>{{ supplier.Street }}</td>
                            <td class='verticalAlignMiddle hidden-480'>{{ supplier.Postal_Code }}</td>
                            <td class='verticalAlignMiddle hidden-480'>{{ supplier.CR }}</td>
                            <td class='verticalAlignMiddle hidden-480'>{{ supplier.Website }}</td>
                            <td class='verticalAlignMiddle hidden-480'>{{ supplier.Notes }}</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>

and the vue and ajax:

<script>
export default {
    data() {
        return {
            suppliers: [],
        }
    },
    methods: {
        fetchSuppliers() {
            this.$http.get('http://localhost/curemodules/public/suppliers/list')
            .then(response => {
                this.suppliers = JSON.parse(response.bodyText).data;
            });
        }
    },
    created() {
        this.fetchSuppliers();
    },
}

回答1:

Once initialized, DataTables does not automatically reparse the DOM. Here's a relevant FAQ:

Q. I append a row to the table using DOM/jQuery, but it is removed on redraw.

A. The issue here is that DataTables doesn't know about your manipulation of the DOM structure - i.e. it doesn't know that you've added a new row, and when it does a redraw it will remove the unknown row. To add, edit or delete information from a DataTable you must use the DataTables API (specifically the row.add(), row().data() and row().remove() methods to add, edit and delete rows.

However, you can call table.destroy() to destroy the current instance before reinitializing it. The key is to delay the reinitialization until $nextTick() so that Vue can flush the DOM of the old DataTables. This is best done from a watcher on suppliers so that the DataTables reinitialization is done automatically when the variable is updated in fetchSuppliers().

mounted() {
  this.dt = $(this.$refs.suppliersTable).DataTable();
  this.fetchSuppliers();
},
watch: {
  suppliers(val) {
    this.dt.destroy();
    this.$nextTick(() => {
      this.dt = $(this.$refs.suppliersTable).DataTable()
    });
  }
},

demo



回答2:

I know this is a bit late answer but I just encountered this problem just today and my only solution for this issue is using setTimeout function.After fetching data using axios I set a bit of delay then init the data-table. With this work around v-for works fine.

See below for my code.

GetDepartmentList(){
           axios.get('department')
                .then((response) => {

                    this.departmentList = response.data;
                    // this.dataTable.rows.add(response.data).draw();
                    setTimeout(() => $('#department-data-table').DataTable(), 1000);

                })
                .catch((error) => {
                    if (error.response.status == 401) {
                        alert('User session has expired. Please login again.');
                        location.replace("/login");
                    }
                });
        },

Also you can use .rows.add() function if you want to draw row data in the table without using v-for of vue. Refer to this doc.



回答3:

You can using Axios in Vuejs, you try see the following above:

<template>
    <div class="danhsach">
      <h2>{{title}}</h2>
        <table class="table">
            <thead>
              <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Password</th>
                <th>Age</th>
              </tr>
            </thead>
            <tbody>
                <tr v-for='data in datas'>
                  <td>{{data.id}}</td>
                  <td>{{data.name}}</td>
                  <td>{{data.password}}</td>
                  <td>{{data.age}}</td>
                </tr>
                 
            </tbody>
        </table>
    </div>
 </template>
 <script>
  export default{
      data(){
        return {
          title:"Tile Lists",
          datas:[]
        }
      },
      created:function(){
        this.danhsach_user();
      },
      methods:{
          danhsach_user(){
           this.axios.get('https://599f807effe73c0011b9fcc5.mockapi.io/api/user').then((response)=>{
             this.datas=response.data;
            });
          }
      }
  }
 
 
 </script>