How to sort an iron-list in Polymer 1.0?

2019-02-15 05:08发布

问题:

I am looking to sort data in an iron-list (and also sort items as they are added into the data array).

Sample (unsorted) json data:

[
  {"name": "Zebra"},
  {"name": "Alligator"},
  {"name": "Lion"}
]

I have tried using the indexAs property to sort an iron-list as follows but the API isn't clear how to use it:

<iron-ajax url="./data.json" last-response="{{data}}" auto></iron-ajax>
<iron-list items="[[data]]" as="item" index-as="name" class="fit">
  <template>
    <div>
      Name: <span>[[item.name]]</span>
    </div>
  </template>
</iron-list>

回答1:

I'm not exactly sure if there's more native Polymer way to do this, but it's not too complex to build the sorting logic yourself.

The idea is to listen to the response event, sort the data from the service and then bind the items of the iron-list to the sortedData.

You will need to add on-response="_onResponseReceived" to your iron-ajax. And then it's just a matter of sorting the returned data.

_onResponseReceived: function () {
    this.sortedData = this.data.sort(this._compare);
},

_compare: function (a, b) {
    if (a.name < b.name)
        return -1;
    if (a.name > b.name)
        return 1;
    return 0;
}

Of course the iron-list now needs to be updated to

<iron-list items="[[sortedData]]" ...>


回答2:

With Polymer 1.2.4 if you want to sort an iron-list in a dynamic fashion you can also take advantage of this.querySelector('iron-list').notifyResize(); to force a refresh after you update the sortedItems array in your observer. This is a hack but if you don't do this unfortunately polymer doesn't refresh the list for you. Let's sort by id or name our items:

<template>
    <paper-icon-button icon="expand-more" on-tap="_sortItems" sort-option="id"></paper-icon-button>
    <paper-icon-button icon="expand-more" on-tap="_sortItems" sort-option="name"></paper-icon-button>

    <iron-list items="[[sortedItems]]">
        <template>
            <p>[[item.name]]<p>
        </template>
    </iron-list>
</template>
...
properties: {
    ...
    sortByTerm: {
        type: String,
        value: 'id'
    },
    sortByOrder: {
        type: Number,
        value: -1 // Descending order
    },
},
observers: [
    'sortingObserver(items.*, sortByTerm, sortByOrder)'
],
sortingObserver: function(items, sortByTerm, sortByOrder) {
    var sortedItems = [],
    validSortingOptions = ['id', 'name'];

    if (validSortingOptions.indexOf(sortByTerm) != -1) {
        sortedItems = items.base.sort(this._computeSort(sortByTerm, sortByOrder));
    } else {
        sortedItems = items.base;
    }

    this.set('sortedItems', sortedItems);
    this.querySelector('iron-list').notifyResize();
},
_computeSort: function(property, order) {
    return function(a, b) {
        if (a[property] === b[property]) {
            return 0;
        }
        return (order * (a[property] > b[property] ? 1 : -1));
    };
},
_sortItems: function(e) {
    var sortByTerm = e.currentTarget.getAttribute('sort-option');
    this.set('sortByTerm', sortByTerm);
},
...