-->

Polymer, binding to array items not working

2019-01-27 03:46发布

问题:

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.

回答1:

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.



回答2:

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);