27879

Databinding in Polymer

Question:

<h3>My Goal</h3>

I want to databind the items property <a href="http://jsbin.com/laxaridawa/edit?html,console,output" rel="nofollow">shown in this jsBin</a> -- and have the rendered HTML text output match the value shown in the console.

<h3>What I expect to see...</h3>

<a href="http://jsbin.com/laxaridawa/edit?html,console,output" rel="nofollow">When I open this jsBin</a>, in the right pane labeled <em>output</em>, I expect to see the following in the second line of text:

Lorem,Ipsum,foo,1,bar,1,baz,0,qux,0 <h3>What I actually see...</h3>

Instead, I see:

Lorem,Ipsum,foo,0,bar,0,baz,0,qux,0

But if you click the button labeled <em>Show</em>, and check the console, you will see the following:

console.log Lorem,Ipsum,foo,1,bar,1,baz,0,qux,0

The two don't match.

Question

<blockquote>

How do I update/databind these variables so the output pane matches the console value?

</blockquote>

(Please show a working jsBin if possible.)

<h3>Code</h3> 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>

Answer1:

You can't treat one property as computed <strong>and</strong> 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.

Answer2:

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:

<ol><li>make a copy of the array and return the copy</li> <li>manually call notifyPath to notify that the value has changed</li> </ol>

Here's a <a href="http://jsbin.com/jaxisuhofe/edit?html,console,output" rel="nofollow">jsBin</a> 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 <strong>both</strong> compute and value. Value is simply an initial value, which will immediatly be recalculated because selected's value is set.

<strong>WARNING</strong> 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.

<ol><li>

<a href="http://jsbin.com/kinugekoto/edit?html,console,output" rel="nofollow">jsBin</a> When items is first, the order seems to be items-value, selected-value, items-compute and items-compute sees this.items having the initial value.

</li> <li>

<a href="http://jsbin.com/lelozozaxu/edit?html,console,output" rel="nofollow">jsBin</a> 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, <strong>but if items-compute returns a value</strong>, items-value seems to be never used (check by uncommenting code in _computeItems).

</li> </ol>

Recommend

  • Webcomponentjs polyfill for v1 spec
  • AngularJS directives as “custom” HTML tags: isn't this dangerous and may conflict with future H
  • Javascript Injection prevention on Wordpress
  • App not compatible with Nexus 7 and Acer Iconia a210
  • sh: 1: concurrent: not found while npm start
  • Passing custom CSS to Polymer element
  • Should my be inside my ?
  • Testing polymer 1.0 components with iron-ajax using wct
  • How to prepare a C++ string for sql query
  • Why does IE8 fail to resolve my JQuery selector for a checked radio option?
  • Responsive Form on top of Responsive Image? - Bootstrap
  • Changing media screen makes div overlay
  • How to remove gaps in flexbox?
  • Using Laravel 5.4 pusher
  • How do I include a SWC in an AS2 Flash project?
  • Eliminate partial duplicate rows from result set
  • How to view images from protected folder with php?
  • D3 get axis values on zoom event
  • Zurb Foundation _global.scss meta styles for js?
  • Webgrid not refreshing after delete MVC
  • Display images in Django
  • Custom validator control occupying space even though display set to dynamic
  • JSON response opens as a file, but I can't access it with JavaScript
  • Jquery UI tool tip close icon
  • How to install a .deb file on a jailbroken iphone programmatically?
  • DomPDF {PAGE_NUM} not on first page
  • Change JButton Shape while respecting Look And Feel
  • Javascript simulate pressing enter in input box
  • Uncaught Error: Could not find module `ember-load-initializers`
  • req.body is undefined - nodejs
  • Resize panoramic image to fixed size
  • Updating server-side rendering client-side
  • Modifying destination and filename of gulp-svg-sprite
  • Importing jscolor library in angular 2
  • jqPlot EnhancedLegendRenderer plugin does not toggle series for Pie charts
  • Traverse Array and Display in markup
  • A cron job substitute?
  • using HTMLImports.whenReady not working in chrome
  • Qt: Run a script BEFORE make
  • apache spark aggregate function using min value