[英]Polymer 1.x: Databinding Arrays
I want to databind the selected
property in this element to the DOM (at <div>[[selected]]</div>
). 我想将此元素中的
selected
属性数据绑定到DOM(在<div>[[selected]]</div>
)。
After selecting a state (like "Texas"), I expect the state's name to appear in the upper left next to the pre-selected states of "Colorado,South Dakota" (inside the <div>[[selected]]</div>
tag). 选择一个州(例如“德克萨斯州”)后,我希望该州的名称出现在“科罗拉多州,南达科他州”预选州旁边的左上方(在
<div>[[selected]]</div>
标签)。 But instead, it does not. 但是,事实并非如此。
What's going on here? 这里发生了什么? How can I successfully databind the DOM to the
selected
property? 如何成功将DOM绑定到
selected
属性? And have the DOM update automatically with each new state that is selected and de-selected. 并让DOM自动随着选中和取消选中的每个新状态进行更新。
Follow these steps: 跟着这些步骤:
<div>[[selected]]</div>
<div>[[selected]]</div>
selected
array. selected
阵列中。 This SO answer explains why mutated arrays are not directly observable by the Polymer object . 这个SO答案解释了为什么Polymer对象不能直接观察到变异数组 。
...you are doing work where Polymer cannot see it (ie the array manipulations), and then asking
set
to figure out what happened....您正在做Polymer无法看到的工作(即数组操作),然后要求
set
找出发生了什么。 However, when you callthis.set('selected', selected);
但是,当您调用
this.set('selected', selected);
, Polymer sees that the identity ofselected
hasn't changed (that is, it's the same Array object as before) and it simply stops processing.,Polymer看到
selected
的标识没有改变(也就是说,它与以前的Array对象相同),并且只是停止处理。
So I attempted to solve the problem by creating a new array using the .slice()
method on the original array as follows. 因此,我尝试通过在原始数组上使用
.slice()
方法创建一个新数组来解决此问题,如下所示。
// Sort new 'selected' array _selectedChanged: function(selectedInfo) { var selected = this.selected.slice(); selected.sort(); //this.set('selected', selected); // Uncommenting this line crashes call stack },
This seems to solve the observability problem but creates a side effect issue and crashes the call stack. 这似乎解决了可观察性问题,但产生了副作用,并使调用堆栈崩溃。
<!DOCTYPE html> <head> <meta charset="utf-8"> <base href="https://polygit.org/components/"> <script src="webcomponentsjs/webcomponents-lite.min.js"></script> <link href="polymer/polymer.html" rel="import"> <link href="google-chart/google-chart.html" rel="import"> </head> <body> <dom-module id="x-element"> <template> <style> google-chart { width: 100%; } </style> <br><br><br><br> <button on-tap="_show">Show Values</button> <button on-tap="clearAll">Clear All</button> <button on-tap="selectAll">Select All</button> <div>[[selected]]</div> <google-chart id="geochart" type="geo" options="[[options]]" data="[[data]]" on-google-chart-select="_onGoogleChartSelect"> </google-chart> </template> <script> (function() { // google-chart monkey patch var gcp = Object.getPrototypeOf(document.createElement('google-chart')); gcp.drawChart = function() { if (this._canDraw) { if (!this.options) { this.options = {}; } if (!this._chartObject) { var chartClass = this._chartTypes[this.type]; if (chartClass) { this._chartObject = new chartClass(this.$.chartdiv); google.visualization.events.addOneTimeListener(this._chartObject, 'ready', function() { this.fire('google-chart-render'); }.bind(this)); google.visualization.events.addListener(this._chartObject, 'select', function() { this.selection = this._chartObject.getSelection(); this.fire('google-chart-select', { selection: this.selection }); }.bind(this)); if (this._chartObject.setSelection){ this._chartObject.setSelection(this.selection); } } } if (this._chartObject) { this._chartObject.draw(this._dataTable, this.options); } else { this.$.chartdiv.innerHTML = 'Undefined chart type'; } } }; Polymer({ is: 'x-element', /** / * Fired when user selects chart item. * * @event us-map-select * @param {object} detail Alpabetized array of selected state names. /**/ properties: { items: { type: Array, value: function() { return [ 'Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming', ].sort(); }, }, color: { type: String, value: 'blue', }, options: { type: Object, computed: '_computeOptions(color)', }, selected: { type: Array, value: function() { return []; } }, data: { type: Array, computed: '_computeData(items, selected.length)' }, }, observers: [ '_selectedChanged(selected.length)', ], _computeOptions: function() { return { region: 'US', displayMode: 'regions', resolution: 'provinces', legend: 'none', defaultColor: 'white', colorAxis: { colors: ['#E0E0E0', this.color], minValue: 0, maxValue: 1, } } }, // On select event, compute 'selected' _onGoogleChartSelect: function(e) { var string = e.path[0].textContent.split('Select')[0].trim(), // eg 'Ohio' selected = this.selected, // Array of selected items index = selected.indexOf(string); // If 'string' is not in 'selected' array, add it; else delete it if (index === -1) { this.push('selected', string); } else { this.splice('selected', index, 1); } }, // Sort new 'selected' array _selectedChanged: function(selectedInfo) { var selected = this.selected.slice(); selected.sort(); //this.set('selected', selected); // Uncommenting this line crashes call stack }, // After 'items' populates or 'selected' changes, compute 'data' _computeData: function(items, selectedInfo) { var data = [], selected = this.selected, i = items.length; while (i--) { data.unshift([items[i], selected.indexOf(items[i]) > -1 ? 1 : 0]); } data.unshift(['State', 'Select']); return data; }, clearAll: function() { this.set('selected', []); }, selectAll: function() { this.set('selected', this.items); }, _show: function() { //console.log('items', this.items); console.log('selected', this.selected); //console.log('data', this.data); }, }); })(); </script> </dom-module> <x-element color="red" selected='["Colorado", "South Dakota"]'></x-element> </body> </html>
If you want to bind array you have to use the dom-repeat. 如果要绑定数组,则必须使用dom-repeat。
<template is="dom-repeat" items="[[selected]]">[[item]] </template>
http://jsbin.com/soxedeqemo/edit?html,console,output http://jsbin.com/soxedeqemo/edit?html,控制台,输出
The formatting of dom-repeat
doesn't support proper use of comma delimiters. dom-repeat
的格式不支持正确使用逗号分隔符。 So I used a computed property string instead. 所以我改用了一个计算属性字符串。
<div>[[selectedString]]</div> ... selectedString: { type: String, computed: '_computeSelectedString(selected.length)', }, ... _computeSelectedString: function(selectedInfo) { return this.selected.sort().join(', '); },
Databinding arrays can be tricky. 数据绑定数组可能很棘手。
So here is a complete implementation example . 因此,这是一个完整的实现示例 。
<!doctype html> <head> <meta charset="utf-8"> <base href="https://polygit.org/components/"> <script src="webcomponentsjs/webcomponents-lite.min.js"></script> <link href="paper-button/paper-button.html" rel="import"> </head> <body> <x-element></x-element> <dom-module id="x-element"> <template> <br><br> <paper-button on-tap="_addNew">Click To Add</paper-button> <p> <strong>Items</strong>: <template is="dom-repeat" items="{{items}}"> <span>[[item]] </span> </template> </p> </template> <script> Polymer({ is: 'x-element', properties: { items: { type: Array, value: function() { return ['foo']; } } }, _addNew: function() { var a = this.items; // Clones array a.push('bar'); // Updates "value" console.log('a', a); this.set('items', a.slice()); // Updates "identity" console.log('items', this.items); }, }); </script> </dom-module> </body>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.