jlengrand jlengrand - 11 months ago 48
HTML Question

Item changing in dom-repeat not communicated to other items

We are building a polymer application.
We have an array of elements, which are shown in a component using dom-repeat. Here is an example snippet:

//main component
<h2>List of elements</h2>
<template is="dom-repeat" items="{{elements}}" as="item" indexAs="index">
<another-component element="{{item}}" ident$="{{index}}"></another-component>
</template>


and

//sub component
<h3>{{element.name}}</h3>
<h4>{{element.person.name}}</h4>
<paper-button on-tap="_changeName">Change name!</paper-button>


The objects of the array have some common references. You can see them like this :

//main component
<script>
var fred = {"name": "fred"};
var tom = {"name": "tom"};

Polymer({
is: 'example-component',
properties: {
elements: {
type: Array,
value: [{"name": "Main1", "person": fred}, {"name": "Main2", "person": tom}, {"name": "Main3", "person": fred}],
notify: true
}
}
});
</script>


Now, in my items I want to be able to change a nested element.

In this example, I want item 3's person value to change.

But since item 3's person reference is the same as for item 1, I would also expect person 1 to change.

However, What I do experience is that item 1 is not updated.

There is a complete example setup at this address. (I could get jsfiddle to work with my dependencies properly...).

So far I have tried to look into


  • listeners

  • notifyPath

  • observers



without success.
I also would like to avoid passing my whole array to my items.

I know it would be easily solved using a state object like Redux for example, so unfortunately this cannot be a solution here.

I have found a lot of resources in the internet on how to get data to bubble down, but not to bubble up like I am trying to do now.

Any help would be appreciated.




The complete code for reference :

Main component

<link rel="import" href="/polymer/polymer.html">
<link rel="import" href="/components/another-component/another-component.html">

<dom-module id="example-component">
<template>
<style>
:host {
display: block;
}
</style>

<h1>Example</h1>

<h2>List of elements</h2>
<template is="dom-repeat" items="{{elements}}" as="item" indexAs="index">
<another-component element="{{item}}" ident$="{{index}}"></another-component>
</template>

</template>
<script>
var fred = {"name": "fred"};
var tom = {"name": "tom"};

Polymer({
is: 'example-component',
properties: {
elements: {
type: Array,
value: [{"name": "Main1", "person": fred}, {"name": "Main2", "person": tom}, {"name": "Main3", "person": fred}],
notify: true
}
}
});
</script>
</dom-module>


Sub component




<dom-module id="another-component">
<template>
<style>
:host {
display: block;
}
</style>

<h3>{{element.name}}</h3>
<h4>{{element.person.name}}</h4>
<paper-button on-tap="_changeName">Change name!</paper-button>

</template>
<script>
Polymer({
is: 'another-component',
properties: {
element: {
type: Object,
notify: true
}
},

_changeName: function(){
this.set('element.person', {"name": "bobby"});
this.notifyPath('elements');
this.notifyPath('element');
this.notifyPath('element.person');

}
});
</script>
</dom-module>


Thanks,

Answer Source

Child component is not changing the value of your parent component. As suggested by Jacob Miles, you need to fire an event to change the value. Then listen from the parent element where you can notify the changes of the whole elements array.

Here is the plnkr link : http://plnkr.co/edit/tuqKh4ANUTspa05GZ9mi?p=preview

Child component i.e. another-component is firing an event 'change-name':

this.fire('change-name', {"newPersonName" : "bobby","index":this.i });.

Parent component i.e. example-component is listening to that event and notifying the changes:

this.addEventListener('change-name', function (e) {
     this.elements[e.detail.index].person.name = e.detail.newPersonName;

     for(var i =0; i< this.elements.length; i++){
             this.notifyPath('elements.'+i+'.person.name'); 
     }

 });

To notify we need to use the exact path that changed, so I kept the notifyPath in loop (I did not find other way). I hope this helps.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download