问题
My Goal
I want to databind the items
property shown in this jsBin -- and have the rendered HTML text output match the value shown in the console.
What I expect to see...
When I open this jsBin, in the right pane labeled output, I expect to see the following in the second line of text:
Lorem,Ipsum,foo,1,bar,1,baz,0,qux,0
What I actually see...
Instead, I see:
Lorem,Ipsum,foo,0,bar,0,baz,0,qux,0
But if you click the button labeled Show, and check the console, you will see the following:
console.logLorem,Ipsum,foo,1,bar,1,baz,0,qux,0
The two don't match.
Question
How do I update/databind these variables so the output pane matches the console value?
(Please show a working jsBin if possible.)
Code
http://jsbin.com/laxaridawa/edit?html,console,output<!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">
</head>
<body>
<dom-module id="x-element">
<template>
<button on-tap="_show">Show</button>
<div>{{selected}}</div>
<div>{{items}}</div>
</template>
<script>
(function(){
Polymer({
is: 'x-element',
properties: {
items: {
type: Array,
notify: true,
reflectToAttribute: true,
computed: '_computeItems(selected)',
value: function() {
return [['Lorem', 'Ipsum'], ['foo', 0], ['bar', 0], ['baz', 0], ['qux', 0],];
}
},
selected: {
type: Array,
notify: true,
reflectToAttribute: true,
},
},
_computeItems: function(a) {
var out = this.items,
selectedLength = a.length,
i = out.length;
while(i---1){
var j = selectedLength;
while(j--) {
if(a.indexOf(out[i][0])===-1){
out[i][1] = 0;
}
else if(a.indexOf(out[i][0])>-1){
out[i][1] = 1;
}
else {
console.log('Error: Undefined index of selected item');
}
}
}
return out;
},
ready: function(){
this.set('items', this._computeItems(this.seletcted));
},
_show: function() {
console.log('Selected: ' + this.selected);
console.log('Items: ' + this.items);
},
});
})();
</script>
</dom-module>
<x-element
selected='["foo","bar"]'
></x-element>
</body>
回答1:
You can't treat one property as computed and have a value. Only one of those at one time.
You don't need to invoke recalculation of a computed property. When the property listed in the arguments of the computed
function the computed property is recalculated automatically. In your case every time selected
changes.
回答2:
As far as I've found out, the problem is caused by you editing the items
array in place.
It would seem, that after running the compute function _computeItems
, Polymer evaluates whether the value has changed by comparing references. Since you've reused the array, the reference didn't change and changes aren't propagated further in the framework (both to bindings and other computed properties, see
jsBin below).
I've found two ways to make it work:
- make a copy of the array and return the copy
- manually call notifyPath to notify that the value has changed
Here's a jsBin with example fixes. Replace one of the three lines inside _computeItems
with it's commented version and it should work. I've also added a computed property that depends on items, to show that without the fix, that property isn't recalculated properly either.
Edit: I'd like to point out, that this seems to mean that it's perfectly correct to have a property that has both compute
and value
. Value is simply an initial value, which will immediatly be recalculated because selected
's value is set.
WARNING
If both items
and selected
have an initial value and items
is computed based on selected
, things get hairy - compute may be run before an initial value is set, depending on declaration order.
jsBin When
items
is first, the order seems to be items-value, selected-value, items-compute and items-compute seesthis.items
having the initial value.jsBin When
selected
is declated first, then selected-value is ran first which triggers items-compute. Now, if items-compute returns undefined, items-value is taken, but if items-compute returns a value, items-value seems to be never used (check by uncommenting code in_computeItems
).
来源:https://stackoverflow.com/questions/35172641/databinding-in-polymer