ratiw / vue-table

data table simplify! -- vuetable is a Vue.js component that will automatically request (JSON) data from the server and display them nicely in html table with swappable/extensible pagination component.
MIT License
1.83k stars 303 forks source link

Table does not render after props change #146

Closed hallosascha closed 7 years ago

hallosascha commented 7 years ago

Thanks for your great work, I'm loving the vuetable component!

My issue: (Using vue 1.0 and vuetable 1.5.3) I want to be able to switch between different tables. The way I'm doing this, is by including your component with dynamic properties. When selecting a different table, the props change (for example the 'fields' property). I'm also issuing a vuetable:reload event. Inspecting the component with vue-devtools this all seems to work (i.e. the properties change and different data is being loaded as expected).

BUT: for some reason the new table just doesn't show up! The pagination component does show up, but no table. No table heading and no table content. This should be basic vue functionality, using dynamic properties, so I'm just not getting why this fails.

Any ideas, of why this issue might occur, are really appreciated!

ratiw commented 7 years ago

@hallosascha It's hard to tell without seeing the code. My guess is that the vuetable:reload was broadcasted/dispatched before the dynamic properties finished updating their values. You may try calling vuetable:reload inside vm.$nextTick().

hallosascha commented 7 years ago

@ratiw Thanks for the quick reply. I'm already using the vm.$nextTick() method and I'm also able to see in the devtools, that I'm fetching the correct data. I'll try to provide some code (not a working example, but the main gist) - maybe you can have a look at it. I believe this issue must be related to vuetable, I'm sorry if not.

Okay, so in my html I use your vuetable component somehow like this:

<vuetable
  :api-url="table_settings[current_table].api_url"
  :fields="table_settings[current_table].columns"
></vuetable>

In my root vue instance I have the following data structure:

  data: {
    current_table: 'name_of_table_1',

    table_settings: {
      name_of_table_1: {
        columns: ['table_1.field1', 'table_1.field2'],
        api_url: '/table_1'
      },

      name_of_table_2: {
        columns: ['table_2.field1', 'table_2.field2'],
        api_url: '/table_2'
      }
}

And also in my root instance, I'm listening to an tableChangeEvent as follows:

  events: {
    'tableChangeEvent': function(table) {
      this.current_table = table;
      this.$nextTick(function() {
        this.$broadcast('vuetable:refresh');
      });
    }
  }

When I first load the page, table_1 is being rendered correctly. But when I trigger the tableChangeEvent with table_2 as a parameter, the properties of the vuetable component are set correctly (as I can see in the devtools) and also the correct data is being fetched, but the table does not render.

The code provided is of course highly simplified, and I could not test, if this reproduces the issue, but maybe it gives you a better idea of what I'm trying to do. Maybe I'm completely missing something about vue.js.

Hope you have any further ideas and thanks for your time!

ratiw commented 7 years ago

@hallosascha Most of the code looks fine to me, except the tableChangeEvent in the events section.

I think it should look like this

  events: {
    'tableChangeEvent': function(table) {
      this.current_table = table;
      var vm = this;
      this.$nextTick(function() {
        vm.$broadcast('vuetable:refresh');
      });
    }
  }

Let's see if it solves the problem.

hallosascha commented 7 years ago

@ratiw Thanks for looking at the code. Unfortunately your proposal does not solve the issue. The vuetable is fetching the correct data. If I inspect the component, I can see, that the tableData is filled correctly with the expected data.

But, one other thing I noticed, is, that when switching the tables, I get the warning

You need to define "detail-row-id" in order for detail-row feature to work!

which is strange, because I do set this property (for simplicity not in the code provided above, but in my running program I do set that property in a similar way as I'm setting the api-url and the fields property.) So it does seem, as if at the moment of rendering the table, the properties are not all set yet.

By the way, the html rendered looks like this:

<table class="vuetable table-hover">
        <thead>
            <tr>

            </tr>
        </thead>
        <tbody>
                <tr render=""></tr>
                <tr render=""></tr>
                <tr render=""></tr>
                 ...            
        </tbody>
</table>

Okay, thanks again for your time spent on my issue. I start believing, that the issue might be related to some vue.js reactivity issues, which are not related with your component.

ratiw commented 7 years ago

@hallosascha Sorry, couldn't be of any help more than that. Hope you can find around it.

hallosascha commented 7 years ago

@ratiw Thanks for trying! If I find the reason for this issue, I'll let you know.

hallosascha commented 7 years ago

@ratiw Oh, I finally found the problem! When the vuetable is first created, normalizeFields() is called. If later I change the fields, I have to call normalizeFields() again. This could be handled by adding this new event to the Vuetable.vue:

'vuetable:fieldsChange': function() {
    this.normalizeFields()
}
ratiw commented 7 years ago

@hallosascha Oh, yes. That is exactly the reason!

You will have wait a little bit though as I'm quite occupy with other works, unless you want to send the PR for this. :)