Tengo una dom-repeat y otra dom-repeat anidadas en su interior. El exterior está vinculado a una matriz calculada. Cuando hago cambios en la matriz principal, se observan los cambios (lo que significa que se activa el código del observador), pero los cambios no se reflejan en la IU / dom-repeat.

Aquí hay un ejemplo de mi código. Al hacer clic en div dentro del segundo dom-repeat se activa la función handleItemTap, que luego realiza un cambio en la matriz principal. A continuación, se observa este cambio y se vuelve a calcular la matriz calculada; sin embargo, agregar IsChecked al objeto principal no afecta la casilla de verificación en la interfaz de usuario, que se supone que está vinculada a la propiedad IsChecked. ¿Qué estoy haciendo mal?

<template is="dom-repeat"
          items="[[outerComputedArray]]" as="group"
          id="groupRepeater">
    <div class="group-container">       
        <template is="dom-repeat"
                  items="[[group.InnerArray]]" as="sesh">
            <div on-tap="handleItemTap">
                <paper-checkbox id="paperCheckboxId"
                                checked="[[sesh.IsChecked]]"></paper-checkbox>
            </div>
        </template>
    </div>
</template>

...

static get properties() {
    return {
        'parentArray': Array,
        'outerComputedArray': {
            type: Array,
            computed: 'computeOuterArray(parentArray.*)'
        }
    }
}

computeOuterArray(parentArray) {
    if (!(typeof parentArray.base === 'undefined' || parentArray.base == null || parentArray.base.length == 0)) {
        let groupedGrid = parentArray.base.reduce((a, b) => {
            a = a || [];
            let idx = a.findIndex(x => x.PaymentType == b.PaymentType);
            if (idx == -1) {
                let newArray = [];
                newArray.push(b);
                a.push({ 'PaymentType': b.PaymentType, 'InnerArray': newArray });
            }
            else {
                a[idx].InnerArray.push(b);
            }
            return a;
        }, []).map(x => {
            x.Total = x.InnerArray.map(y => y.TotalAmount).reduce((a, b) => a + b, 0);
            return x;
        });
        groupedGrid.sort((a, b) => a.PaymentType.localeCompare(b.PaymentType));

        return groupedGrid;
    }

    return [];
}

handleItemTap(e) {
    let idx = this.parentArray.findIndex(x => x.id == e.model.sesh.id);
    this.set(`parentArray.${idx}.IsChecked`, !(!!e.model.sesh.IsChecked));
}
1
codeMonkey 20 feb. 2018 a las 23:18

2 respuestas

La mejor respuesta

Realmente aprecio que @ mary-shaw haya intentado ayudar, pero no pude hacer funcionar esas sugerencias. Esto es lo que se me ocurrió por ahora. Puse un observador en outerComputedArray que actualiza una segunda matriz, una nueva propiedad llamada selectedIds, con los elementos para los que se ha cambiado la propiedad IsChecked. Luego agregué otra función informática que verifica si selectedIds tiene la misma propiedad id que el objeto en el dom-repeat más interno.

<template is="dom-repeat"
          items="[[outerComputedArray]]" as="group">
    <div class="group-container">       
        <template is="dom-repeat"
                  items="[[group.InnerArray]]" as="sesh">
            <div on-tap="handleItemTap">
                <paper-checkbox id="paperCheckboxId"
                                checked="[[computeIsChecked(selectedIds.*, sesh.id)]]"></paper-checkbox>
            </div>
        </template>
    </div>
</template>

...
<script>
    static get properties() {
        return {
            'parentArray': Array,
            'outerComputedArray': {
                type: Array,
                computed: 'computeOuterArray(parentArray.*)'
            },
            'selectedIds': Array
        }
    }

    static get observers() {
        return [
            'onOuterComputedArrayChanged(outerComputedArray.*)'
        ]
    }

    onOuterComputedArrayChanged(outerComputedArray) {
        if (!(typeof outerComputedArray.base === 'undefined' || outerComputedArray.base == null || outerComputedArray.base.length == 0)) {
            this.set('selectedIds', outerComputedArray.base.filter(x => x.InnerArray.some(y => !!y.IsChecked)).map(x => x.InnerArray.filter(y => !!y.IsChecked)).reduce((a, b) => a.concat(b), []).map(x => x.id));
        }
    }

    computeIsChecked(selectedIds, id) {
        if (!(typeof selectedIds.base === 'undefined' || selectedIds.base == null || selectedIds.base.length == 0)) {
            return selectedIds.base.some(x => x == id);
        }

        return !!0;
    }

    computeOuterArray(parentArray) {
        if (!(typeof parentArray.base === 'undefined' || parentArray.base == null || parentArray.base.length == 0)) {
            let groupedGrid = parentArray.base.reduce((a, b) => {
                a = a || [];
                let idx = a.findIndex(x => x.PaymentType == b.PaymentType);
                if (idx == -1) {
                    let newArray = [];
                    newArray.push(b);
                    a.push({ 'PaymentType': b.PaymentType, 'InnerArray': newArray });
                }
                else {
                    a[idx].InnerArray.push(b);
                }
                return a;
            }, []).map(x => {
                x.Total = x.InnerArray.map(y => y.TotalAmount).reduce((a, b) => a + b, 0);
                return x;
            });
            groupedGrid.sort((a, b) => a.PaymentType.localeCompare(b.PaymentType));

            return groupedGrid;
        }

        return [];
    }

    handleItemTap(e) {
        let idx = this.parentArray.findIndex(x => x.id == e.model.sesh.id);
        this.set(`parentArray.${idx}.IsChecked`, !(!!e.model.sesh.IsChecked));
    }
</script>
0
codeMonkey 22 feb. 2018 a las 01:57

Parece que el problema aquí es la comprobación de suciedad del objeto Polímero. Se usa para acelerar Polymer, pero a veces la verificación sucia no funciona (por ejemplo, cuando cambia elementos en una matriz). Para evitarlo, debe utilizar datos mutables mixin.

Primero, debe traer el mixin cuando declare su elemento.

class MyMutableElement extends Polymer.MutableData(Polymer.Element) { ... }

También debe agregar el indicador de datos mutables a su repetición dom.

<template is="dom-repeat" items="[[outerComputedArray]]" as="group" id="groupRepeater" mutable-data>

Si aún no funciona, intente agregar algo como esto al final de su función computeOuterArray, también (pero solo si realmente cambia la matriz).

timeout(() => { this.notifyPath('outerComputedArray') }, 10)

0
Mary Shaw 20 feb. 2018 a las 21:55