简体   繁体   English

聚合物1.x:数据绑定数组

[英]Polymer 1.x: Databinding Arrays

Objective 目的

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. 但是,事实并非如此。

Question

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自动随着选中和取消选中的每个新状态进行更新。

Reproduce the Problem 重现问题

Follow these steps: 跟着这些步骤:

  1. Open this jsBin . 打开此jsBin
  2. Observe the pre-selected states are Colorado and South Dakota. 观察预选的州是科罗拉多州和南达科他州。
  3. Notice Colarado and South Dakota are listed in the upper left. 注意Colarado和South Dakota在左上方列出。
  4. Click Texas. 单击德克萨斯。
  5. Observe the state of Texas is selected in the chart. 观察在图表中选择的德克萨斯州。
  6. ❌ Notice the state of Texas is not included in the list of selected states in the upper left. ❌请注意,在左上方的所选州列表中未包含德克萨斯州。 ie, <div>[[selected]]</div> <div>[[selected]]</div>
  7. Click the button labeled "Show Values" and observe in the console that "Texas" is included in the selected array. 单击标记为“显示值”的按钮,然后在控制台中观察到“ Texas”已包含在selected阵列中。

Attempted solution using .slice() crashes 使用.slice()的尝试解决方案崩溃

This SO answer explains why mutated arrays are not directly observable by the Polymer object . 这个SO答案解释了为什么Polymer对象不能直接观察到变异数组

@ScottMiles writes: @ScottMiles写道:

...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 call this.set('selected', selected); 但是,当您调用this.set('selected', selected); , Polymer sees that the identity of selected 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()方法创建一个新数组来解决此问题,如下所示。

http://jsbin.com/yosajuwime/1/edit?html,console,output http://jsbin.com/yosajuwime/1/edit?html,控制台,输出
 // 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. 这似乎解决了可观察性问题,但产生了副作用,并使调用堆栈崩溃。

Source 资源

http://jsbin.com/yosajuwime/1/edit?html,console,output http://jsbin.com/yosajuwime/1/edit?html,控制台,输出
 <!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. 所以我改用了一个计算属性字符串。

http://jsbin.com/ruduwavako/1/edit?html,console,output http://jsbin.com/ruduwavako/1/edit?html,控制台,输出
 <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 . 因此,这是一个完整的实现示例

http://jsbin.com/xonanucela/edit?html,console,output http://jsbin.com/xonanucela/edit?html,控制台,输出
 <!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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM