Polymer 1.0:排序铁列表
Polymer 1.0: Sorting iron-list
Google 的 Polymer 创作者声称我们可以手动排序 <iron-list>
(resolving this issue, perhaps?)。
Polymer Slack Site 上的@emmanuel:
You can set list.items = newItems
and that will refresh the list.
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));
(我注释掉了所有失败的尝试。)
- 注意控制台日志验证控制值。
- 还有一个在线控制值监视器。
- This proves the sorting logic.
http://jsbin.com/xoqubecado/edit?html,输出
<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>
根据@rob,Polymer Slack Site:(归功于@arthur 的解决方案!)
here's a version that sorts: http://jsbin.com/mabadi/2/edit?html,output
the main issue is that if you change the contents of an array, polymer has no idea that you've done that (it can't see inside of an array). So you need to create a copy of your data, sort it, and set that as the new value
it may be helpful to have a separate variable for firebaseItems and sortedItems. That way you don't end up accidentally writing back to firebase
also make sure you give iron-list a height
height: 100% or something like that. And make sure its container has a height as well
http://jsbin.com/vizexodoyi/1/edit?html,输出
<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 question and the performance comparison of different solutions here。
一个明显的性能改进可能是:
// Reference for below:
//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];
}
Google 的 Polymer 创作者声称我们可以手动排序 <iron-list>
(resolving this issue, perhaps?)。
Polymer Slack Site 上的@emmanuel:
You can set
list.items = newItems
and that will refresh the list.
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));
(我注释掉了所有失败的尝试。)
- 注意控制台日志验证控制值。
- 还有一个在线控制值监视器。
- This proves the sorting logic.
<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>
根据@rob,Polymer Slack Site:(归功于@arthur 的解决方案!)
http://jsbin.com/vizexodoyi/1/edit?html,输出here's a version that sorts: http://jsbin.com/mabadi/2/edit?html,output
the main issue is that if you change the contents of an array, polymer has no idea that you've done that (it can't see inside of an array). So you need to create a copy of your data, sort it, and set that as the new value
it may be helpful to have a separate variable for firebaseItems and sortedItems. That way you don't end up accidentally writing back to firebase
also make sure you give iron-list a height
height: 100% or something like that. And make sure its container has a height as well
<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 question and the performance comparison of different solutions here。
一个明显的性能改进可能是:
// Reference for below:
//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];
}