Saulis / iron-data-table

iron-data-table is a Web Component for displaying data as a table or grid. Built on top of iron-list using Polymer.
Apache License 2.0
147 stars 65 forks source link

Dynamic columns broken #148

Open depeele opened 8 years ago

depeele commented 8 years ago

Issue #10 (Any plans to support dynamic columns?) was resolved very quickly via PR #13 back in March 2016.

I'm just diving back in to make use of iron-data-table only to find that dynamic columns are no longer working.

The following, which worked properly with the (now deleted) feature/dynamic-columns branch and after PR #13 was pulled into master, no longer works properly. The header and first column render as expected, but the dynamic content of the non-header columns are no longer rendered at all:

<html>
 <head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="chrome=1" />
  <title>`iron-data-table` test</title>

  <script src="lib/webcomponentsjs/webcomponents-lite.js"></script>

  <link href="lib/polymer/polymer.html" rel="import" />
  <link href="lib/iron-data-table/iron-data-table.html" rel="import" />
 </head>
 <body>
  <section class='main-content'>
   <template id="scope" is="dom-bind">
    <iron-data-table items="{{Aitems}}">
      <!-- column 1 { -->
      <data-table-column>
        <template is="header">th</template>
        <template><div class='A-card'>{{ item.name }}</div></template>
      </data-table-column>
      <!-- column 1 } -->
      <!-- column 2..n { -->
      <template is="dom-repeat" items="{{Bitems}}" as="bItem" index-as="bdex">
        <data-table-column>
          <template is="header">{{bItem.name}}</template>
          <template>
            <div class='A-card'>{{getItem(bdex, index)}}</div>
          </template>
        </data-table-column>
      </template>
      <!-- column 2..n } -->
    </iron-data-table>
   </template>
  </section>

  <script>
  (function() {
    var A = [
        {name:'A1'},
        {name:'A2'},
        {name:'A3'},
        {name:'A4'},
    ];
    var B = [
        {name:'B1', data:['AB1,1','AB1,2','AB1,3','AB1,4']},
        {name:'B2', data:['AB2,1','AB2,2','AB2,3','AB2,4']},
        {name:'B3', data:['AB3,1','AB3,2','AB3,3','AB3,4']},
        {name:'B4', data:['AB4,1','AB4,2','AB4,3','AB4,4']},
    ];
    var $scope  = document.querySelector('#scope');

    $scope.getItem = function(bdex, adex) {
        var b   = Bitems[bdex];
        return b.data[adex];
    };
    $scope.Aitems = A;
    $scope.Bitems = B;
  }());
  </script>
 </body>
</html>
Saulis commented 8 years ago

First, var b = Bitems[bdex]; should be var b = $scope.Bitems[bdex]

Secondly, seems like there's some issue with the dom-repeat / iron-list element. The bdex variable is not propagated correctly to the underlying column <template>. You can see that by simply adding a [[bdex]] variable inside the cell template – nothing shows except on the first row.

As a workaround, you can bind properties to <data-table-column> and use them inside the template:

<template is="dom-repeat" items="{{Bitems}}" as="bItem" index-as="bdex">
  <data-table-column bdex="[[bdex]]" bitem="[[bItem]]">
    <template is="header">{{bitem.name}}</template>
       <template>
          <div class='A-card'>{{getItem(column.bdex, index)}}</div>
        </template>
   </data-table-column>
</template>

See: http://jsbin.com/nudaci/edit?html,output

depeele commented 8 years ago

My bad with the var b = $scope.Bitems[bdex]

Thanks for the work-around!

When I first noticed the issued, I did see only the first row being properly filled.

With a minor change it appears that only the non-header template seems to be losing bindings (although it's also the only one actually being repeated):

<template is="dom-repeat" items="{{Bitems}}" as="bItem" index-as="bdex">
  <data-table-column zdex="[[bdex]]">
    <template is="header">[[bItem.name]] : [[bdex]]</template>
    <template>
      <div class='A-card'>[[getItem(column.zdex, index)]] : [[bdex]]</div>
    </template>
  </data-table-column>
</template>

Results in:

th B1 : 0 B2 : 1 B3 : 2 B4 : 3
A1 AB1,1 : 0 AB2,1 : 1 AB3,1 : 2 AB4,1 : 3
A2 AB1,2 : AB2,2 : AB3,2 : AB4,2 :
A3 AB1,3 : AB2,3 : AB3,3 : AB4,3 :
A4 AB1,4 : AB2,4 : AB3,4 : AB4,4 :
andrewillard commented 8 years ago

Hi Saulis, First of all, contrats for the iron-data-table, it's awesome!!!

About this problem, do you know how to solve it? Thanks

Saulis commented 8 years ago

Hi!

Right now I don't 😄 And I'm not sure if I'll have enough time to really look into unfortunately... Also, Polymer 2.0 is coming that might sort this problem – needs to be tested at some point.

Feel free to give me a hand if you can 😄

andrewillard commented 8 years ago

Hi Saulis, I created a PR to make column index avaiable, so it's possible to know what data I need to use in beforeCellBind (row x column). Another thing I did was make possible to set the column object during dom-repeat, this way we can have the row and column object in all beforeCellBind.

PR155

Thanks

prajapatin commented 8 years ago

Hi Saulis,

Did you get a chance to look into Andrew's PR? If it is good, are you planning to push it to master anytime soon?

Saulis commented 8 years ago

Hi @prajapatin sorry for the delay, the PR looks ok otherwise, but I need some more info about the use case for columnItem

prajapatin commented 7 years ago

Hey Guys, just wanted to update here that dynamic columns works with latest code with following approach. I have even more dynamic scenario where column content control (checkbox, dropdown etc.) depends on certain configuration.

 <iron-data-table page-size="10" selection-enabled multi-selection="true" items="{{data.dataItems}}">
    <template is="dom-repeat" items="[[data.tabular.columns]]" as="col" index-as="colIndex">
        <template is="dom-if" if="[[_isCheckBox(col)]]">
           <data-table-column name="[[col.header]]" column-index="{{colIndex}}">
            <template>
    <paper-checkbox checked$="{{_columnValue(item, column.columnIndex)}}"></paper-checkbox>
            </template>
          </data-table-column>
        </template>
        <template is="dom-if" if="[[_isTextArea(col)]]">
            <data-table-column name="[[col.header]]" column-index="{{colIndex}}">
            <template>
         <paper-textarea value="{{_columnValue(item, column.columnIndex)}}"></paper-textarea>
            </template>
           </data-table-column>
        </template>
                 .
                 .
                 . etc.
    </template>
   </iron-data-table>