聚合物1.0:排序铁列表

时间:2015-12-01 08:35:02

标签: polymer polymer-1.0

Google的Polymer创作者声称我们可以手动排序<iron-list>resolving this issue, perhaps?)。

Also see this issue

Polymer Slack Site上的@emmanuel:

  

您可以设置list.items = newItems,这将刷新列表。

Here is my code。但它不起作用。请帮忙。

这部分代码似乎是问题所在。
//this.$.list.items = this.items.sort(this._computeSort(val, ord));
//this.items = this.items.sort(this._computeSort(val, ord));
//this.items.sort(this._computeSort(val, ord));
//this.$.list.items = this.items.sort(this._computeSort(val, ord));

(我注意到我尝试失败的一切。)

JSBin link

http://jsbin.com/xoqubecado/edit?html,output
<html>

<head>
  <title>My Element</title>
  <script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.js"></script>
  <script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"></script>
  <base href="http://element-party.xyz/" />
  <link rel="import" href="all-elements.html" />
</head>

<body>
  <dom-module id="my-element">
    <template>
    <style>
      h3 {
        margin-bottom: 0px;
      }
      iron-list {
        padding-bottom: 16px;
      }
      .item {
        @apply(--layout-horizontal);
        margin: 16px 16px 0 16px;
        padding: 20px;
        border-radius: 8px;
        background-color: white;
        border: 1px solid #ddd;
       }
    </style>
    <firebase-collection location="https://dinosaur-facts.firebaseio.com/dinosaurs" data="{{items}}">
    </firebase-collection>
    <h3>Controls</h3>
    <paper-dropdown-menu label="Sort by">
      <paper-menu class="dropdown-content" selected="{{sortVal}}" attr-for-selected="data-sortby">
        <paper-item data-sortby="order">Order</paper-item>
        <paper-item data-sortby="height">Height</paper-item>
      </paper-menu>
    </paper-dropdown-menu>
    <br>
    <paper-toggle-button checked="{{reverse}}">Reverse</paper-toggle-button>
    <br /><br />
    <br><h3>Monitor Control Values</h3>
    <div>Sort by: [[sortVal]]</div>
    <div>Reverse: [[reverse]]</div>
    <br><h3>Iron-List Output</h3>
    <iron-list id="list" items="[[items]]" as="item">
      <template>
        <div class="item">
          Name: [[item.__firebaseKey__]]<br />
          Order: [[item.order]]<br />
          Height: [[item.height]]
        </div>
      </template>
    </iron-list>
    </template>
    <script>
    (function() {
      Polymer({
        is: "my-element",
        properties: {
          items: {
            type: Array,
          },
          sortVal: {
            type: String,
            value: 'order'
          },
          sortOrder: {
            type: Number,
            value: -1, // High to low
            computed: '_computeSortOrder(reverse)'
          }
        },
        observers: [
          'sortChanged(sortVal, sortOrder)'
        ],
        _computeSortOrder: function(bool) {
          return bool ? 1 : -1;
        },
        sortChanged(val, ord) {
          // Also tried what is commented out
          //this.$.list.items = this.items.sort(this._computeSort(val, ord));
          //this.items = this.items.sort(this._computeSort(val, ord));
          //this.items.sort(this._computeSort(val, ord));
          //this.$.list.items = this.items.sort(this._computeSort(val, ord));
          console.log('ord: ' + ord); // All values logged
          console.log('val: ' + val); // Logs are correct
          console.log('items: ' + this.items); // See console log
        },
        _computeSort: function(val, ord) {
          return function(a, b) {
            if (a[val] === b[val]) {
              return 0;
            }
            return (ord * (a[val] > b[val] ? 1 : -1));
          };
        }
      });
    })();
    </script>
  </dom-module>
  <my-element></my-element>
</body>

</html>

This JSBin proves the sorting logic

1 个答案:

答案 0 :(得分:2)

Per @rob,Polymer Slack Site :(感谢@arthur的解决方案!)

  

这是一个排序的版本:http://jsbin.com/mabadi/2/edit?html,output

     

主要问题是,如果更改数组的内容,聚合物不知道你已经完成了(它无法看到数组内部)。因此,您需要创建数据副本,对其进行排序,并将其设置为新值

     

为firebaseItems和sortedItems提供单独的变量可能会有所帮助。这样你最终不会意外地写回firebase

     

还要确保给铁列表一个高度

     

身高:100%或类似的东西。并确保其容器也具有高度

http://jsbin.com/vizexodoyi/1/edit?html,output
<html>

<head>
  <title>My Element</title>
  <script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.js"></script>
  <script data-require="polymer@*" data-semver="1.0.0" src="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"></script>
  <base href="http://element-party.xyz/" />
  <link rel="import" href="all-elements.html" />
</head>

<body>
  <dom-module id="my-element">
    <template>
    <style>
      h3 {
        margin-bottom: 0px;
      }
      iron-list {
        padding-bottom: 16px;
        height: 100%;
      }
      .item {
        @apply(--layout-horizontal);
        margin: 16px 16px 0 16px;
        padding: 20px;
        border-radius: 8px;
        background-color: white;
        border: 1px solid #ddd;
       }
    </style>
    <firebase-collection location="https://dinosaur-facts.firebaseio.com/dinosaurs" data="{{items}}">
    </firebase-collection>
    <h3>Controls</h3>
    <paper-dropdown-menu label="Sort by">
      <paper-menu class="dropdown-content" selected="{{sortVal}}" attr-for-selected="data-sortby">
        <paper-item data-sortby="order">Order</paper-item>
        <paper-item data-sortby="height">Height</paper-item>
      </paper-menu>
    </paper-dropdown-menu>
    <br>
    <paper-toggle-button checked="{{reverse}}">Reverse</paper-toggle-button>
    <br /><br />
    <br><h3>Monitor Control Values</h3>
    <div>Sort by: [[sortVal]]</div>
    <div>Reverse: [[reverse]]</div>
    <br><h3>Iron-List Output</h3>
    <iron-list id="list" items="[[items]]" as="item">
      <template>
        <div class="item">
          Name: [[item.__firebaseKey__]]<br />
          Order: [[item.order]]<br />
          Height: [[item.height]]
        </div>
      </template>
    </iron-list>
    </template>
    <script>
    (function() {
      Polymer({
      is: "my-element",
      properties: {
        items: {
          type: Array,
        },
        sortVal: {
          type: String,
          value: 'order'
        },
        sortOrder: {
          type: Number,
          value: -1, // High to low
          computed: '_computeSortOrder(reverse)'
        }
      },
      observers: [
        'sortChanged(sortVal, sortOrder)'
      ],
      _computeSortOrder: function(bool) {
        return bool ? 1 : -1;
      },
      sortChanged(val, ord) {
        if (! this.items || this.items.length == 0) {
          return;
        }
        var temp = Array.prototype.slice.call(this.items);
        temp.sort(this._computeSort(val, ord));
        this.items = temp;
        //console.log('ord: ' + ord);
        //console.log('val: ' + val);
        //console.log('items: ' + this.items);
      },
      _computeSort: function(val, ord) {
        return function(a, b) {
          if (a[val] === b[val]) {
            return 0;
          }
          return (ord * (a[val] > b[val] ? 1 : -1));
        };
      }
     });
    })();
    </script>
  </dom-module>
  <my-element></my-element>
</body>

</html>

优化效果

对于对Array.prototype.slice.call(this.items)感兴趣的人,您可能需要study this SO questionperformance comparison of different solutions here

一个明显的性能改进可能是:

// Reference for below: https://stackoverflow.com/questions/3199588/fastest-way-to-convert-javascript-nodelist-to-array
//var temp = Array.prototype.slice.call(this.items);
var temp = [];
var i = this.items.length;
while(i--) {
  //temp.unshift(this.items[i]);
  temp[i] = this.items[i]; 
}