Polymer, binding to array items not working
Asked Answered
C

2

2

In this example (Plunk) there is bind between property and array item.

firstName should change from 'John' to 'Test' on click, but it's not happening.

How to make the property to change on item update?

<script src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html">
<!-- 
 <link rel="import" href="https://cdn.rawgit.com/download/polymer-cdn/1.1.4/lib/paper-input/paper-input.html" />
  -->
<dom-module id="first-el">
  <template>

    <br> firstName should change on click:<br><br>
    firstName: <span>{{employees.employees.0.firstName}}</span>
    <br>
    <br>
    <button on-tap="tap_change_firstName_1">change firstName to: Test</button>


  </template>
  <script>
    (function() {
      'use strict';

      Polymer({
        is: "first-el",

        properties: {
          employees: {
            type: Object,
            notify: true,
          },
        },

        //domReady:
        attached: function() {
          this.async(function() {

                console.log('first: domReady:');
                this.employees = {
                  "employees": [{
                    "firstName": "John",
                    "lastName": "Doe"
                  }]
                };
          });
        },

        tap_change_firstName_1: function() {

              console.log('First: tap_change_firstName_1');
              //update array item property
              this.set('employees.employees.0.firstName', 'Test');

              console.log('New value:');
              console.log(this.employees.employees[0].firstName);
              //here the value is cnahged but that does not reflect in the DOM

        },

      });
    })();
  </script>

</dom-module>

<!-- use the element -->
<first-el></first-el> 

Update:

array-selector (simple example) element can be used for this task too.

Cursor answered 10/12, 2015 at 18:54 Comment(0)
C
2

The set() convenience function just wraps the property setter and the notifyPath call in one. When your data is an array like that, I believe notifyPath is expecting the upper-level array itself and not just a single slice of it.

One way to resolve it (there are probably a few) would be to make that notifyPath call yourself after setting the property directly.

this.employees.employees[0].firstName = 'Test';
this.notifyPath('employees.employees', this.employees.employees);

See new Plunker.

Centroclinal answered 10/12, 2015 at 19:5 Comment(2)
Thanks, this works! Take a notice that set() works fine if the imports are coming from CDN link - commented out import at the top from "href="cdn.rawgit.com..."Cursor
@GoceRibeski that's a great catch! I like calling notifyPath personally, it gives me a little more control. Changing values are just normal calls and you can notify Polymer when you're all done instead of each time.Centroclinal
C
1

Upper solution works only for one change, it does not work for multiple 'name' updates, example: Plunk

Correct solution, from the docs: in this Plunk

Explicit bindings to array items by index isn’t supported

<div>{{arrayItem(myArray.*, 0, 'name')}}</div>
...
// first argument is the change record for the array change,
// change.base is the array specified in the binding
arrayItem: function(change, index, path) {
        // this.get(path, root) returns a value for a path
        // relative to a root object.
        return this.get(path, change.base[index]);
},
...
// change a subproperty
this.set('myArray.1.name', rnd_firstName);
Cursor answered 11/12, 2015 at 9:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.