Reputation: 141
I have 2 components using same array binding for example:
{
title: "food",
data : ["data1", "data2", "data3"]
}
title is on parent component and data is binded from parent to child component to child works with the array.
how can i do to when i remove a array data element notify to parent component?
Here the example.
In the example i have a children with binded array and one method to remove array elements and notify. And parent compontent has a observer named arrayChanges.
if code works parent component has to know about child array length, but it doesnt works.
<script type='module'>
import {PolymerElement, html} from 'https://unpkg.com/@polymer/polymer/polymer-element.js?module';
import {} from 'https://unpkg.com/@polymer/[email protected]/lib/elements/dom-repeat.js?module';
class ParentComp extends PolymerElement {
static get properties() {
return {
myArr: {
type: Array,
observer: "arrayChanges"
},
changes: {
type: String
}
};
}
static get template() {
return html`
<div>[[myArr.title]]</div>
<children-comp data='[[myArr.data]]'></children-comp>
<div>[[changes]]</div>
`;
}
ready(){
super.ready();
this.myArr = {
title : "My component",
data : [
{titulo: "titulo1", comment : "im comment number 1"},
{titulo: "titulo2", comment : "im comment number 2"}
]
}
}
arrayChanges(){
this.changes = "Array length : "+this.myArr.data.length;
console.log("the Array has been changed");
}
}
class ChildrenComp extends PolymerElement {
static get properties() {
return {
data: {
type: Array,
notify: true
}
};
}
static get template() {
return html`
<ul>
<dom-repeat items='[[data]]' >
<template>
<li>
[[index]] )
[[item.titulo]]
[[item.comment]]
<button data-index$='[[index]]' on-click='handle_button'>Borrar</button>
<hr>
</li>
</template>
</dom-repeat>
</ul>
`;
}
handle_button(e){
var index = e.currentTarget.dataset.index;
this.notifyPath("data");
this.splice("data", index, 1);
}
}
customElements.define('children-comp', ChildrenComp);
customElements.define('parent-comp', ParentComp);
</script>
<parent-comp></parent-comp>
Upvotes: 0
Views: 437
Reputation: 138266
The parent component would only handle change-notifications in two-way bindings (using curly brackets). Your data binding incorrectly uses one-way binding (square brackets).
<children-comp data='[[myArr.data]]'></children-comp>
^^ ^^ square brackets: one-way binding
<children-comp data='{{myArr.data}}'></children-comp>
^^ ^^ curly brackets: two-way binding
Also note the simple observer (specified in myArr
-property declaration) does not detect array mutations. You should use a complex observer instead. You could observe data/length changes and/or array mutations:
static get properties() {
return {
myArr: {
// type: Array, // DON'T DO THIS (myArr is actually an object)
type: Object,
// observer: 'arrayChanges' // DON'T DO THIS (doesn't detect array splices)
}
}
}
static get observers() {
return [
'arrayChanges(myArr.data, myArr.data.length)', // observe data/length changes
'arraySplices(myArr.data.splices)', // observe array mutations
]
}
arrayChanges(myArrData, myArrDataLength) {
console.log({
myArrData,
myArrDataLength
})
}
arraySplices(change) {
if (change) {
for (const s of change.indexSplices) {
console.log({
sliceIndex: s.index,
removedItems: s.removed,
addedItems: s.addedCount && s.object.slice(s.index, s.index + s.addedCount)
})
}
}
}
<html>
<head>
<script src="https://unpkg.com/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
</head>
<body>
<script type='module'>
import {PolymerElement, html} from 'https://unpkg.com/@polymer/polymer/polymer-element.js?module';
import {} from 'https://unpkg.com/@polymer/[email protected]/lib/elements/dom-repeat.js?module';
class ParentComp extends PolymerElement {
static get properties() {
return {
myArr: {
type: Array,
},
changes: {
type: String
}
};
}
static get observers() {
return [
'arrayChanges(myArr.data, myArr.data.length)',
'arraySplices(myArr.data.splices)',
]
}
static get template() {
return html`
<div>[[myArr.title]]</div>
<children-comp data='{{myArr.data}}'></children-comp>
<div>{{changes}}</div>
`;
}
ready(){
super.ready();
this.myArr = {
title : "My component",
data : [
{titulo: "titulo1", comment : "im comment number 1"},
{titulo: "titulo2", comment : "im comment number 2"}
]
}
}
arrayChanges(myArr, myArrLength){
this.changes = "Array length : " + myArrLength;
console.log("the Array has been changed", myArr);
}
arraySplices(change) {
if (change) {
for (const s of change.indexSplices) {
console.log({
sliceIndex: s.index,
removedItems: s.removed,
addedItems: s.addedCount && s.object.slice(s.index, s.index + s.addedCount)
})
}
}
}
}
class ChildrenComp extends PolymerElement {
static get properties() {
return {
data: {
type: Array,
notify: true
}
};
}
static get template() {
return html`
<ul>
<dom-repeat items='[[data]]' >
<template>
<li>
[[index]] )
[[item.titulo]]
[[item.comment]]
<button data-index$='[[index]]' on-click='handle_button'>Borrar</button>
<hr>
</li>
</template>
</dom-repeat>
</ul>
`;
}
handle_button(e){
var index = e.currentTarget.dataset.index;
this.notifyPath("data");
this.splice("data", index, 1);
}
}
customElements.define('children-comp', ChildrenComp);
customElements.define('parent-comp', ParentComp);
</script>
<parent-comp></parent-comp>
</body>
</html>
Upvotes: 3