Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

redux state array bound to dom-repeat doesn't reflect items property changes. #103

Open
togonow opened this issue Sep 14, 2017 · 7 comments

Comments

@togonow
Copy link

togonow commented Sep 14, 2017

I have the following element the issue is when changing an employee thru redux action, the changes does not propagate to the dom-repeat, but is reflected when bound directly inside the parent template (e.g. [[employees.0.id]])
I've tried manual re-render of the dom-repeat template e.g. this.$.employees.render() but still does not reflect the updated employee properties
any suggestion?

Note: i'm using v1.01

<dom-module id="employees-info">
    <template>
        [[employees.0.id]]  - [[employees.0.firstname]]  -- [[employees.0.lastname]]
        [[employees.1.id]]  - [[employees.1.firstname]]  -- [[employees.1.lastname]]

        <template is="dom-repeat" items=[[employees]] as=“employee”   id=“employees” >
            <div>id: [[employee.id]]</div>
            <div>firstname: [[employee.firstname]]</div>
            <div>lastname: [[employee.lastname]]</div>

        </template>

    </template>
    <script>
        class EmployeesInfo extends ReduxMixin(Subscriber(Polymer.Element)) {
            static get is() { 
                return 'employees-info' 
            }

            static get properties() {
                return {
                    employees:{
                        type:Array,
                        statePath:'employees'
                    }
                }
            }
        }

        customElements.define(EmployeesInfo.is, EmployeesInfo);
    </script>
</dom-module>    

Now inside the redux store actions, (i've already tried multiple ways to update the array e.g. splice)

    ```
case 'UPDATE_EMPLOYEE_SUCCESS':
            
            return Object.assign({}, state, {
                employees: state.employees.slice().map((employee) =>{ 
                    // update employee bere
                    return employee;  
            }), updating_employee: 'success' });
@jobizzness
Copy link

Plus one this issue. I am facing the same problem. sub properties are not notified on change.

@barnomics
Copy link

I am facing the same issue. The data is definitely updating and observers are firing ... but nothing is happening inside the dom-template.

      static get observers() {
        return [
          '_test(myArray.*)',
        ];
      }

      _test(change) {
       // this all works ...
        console.info(change);
        console.info(this.get('myArray.0.items.length'));
      }

@barnomics
Copy link

barnomics commented Dec 1, 2017

For reasons beyond my understanding, this seems to trigger something to make the dom-repeat update

      static get observers() {
        return [
          '_updateNotifier(myArray.*)',
        ];
      }

      _updateNotifier(change) {
        change.base.forEach((base, i) => {
          this.notifyPath(`${change.path}.${i}.items.length`);
        });
      }

@TimPietrusky
Copy link

TimPietrusky commented Dec 7, 2017

I had the same problem and @pixelass "fixed" it by using https://github.com/kolodny/immutability-helper instead of dealing with state changes on our own (even when we thought that we are creating immutable data):

const myArray = [{ name: 'foo' }, { name: 'bar' }]
const newMyArray = update(myArray, { 0: { $set: { name: 'foobar' } } })

Note: We are using Polymer 3 and https://github.com/tur-nr/polymer-redux/tree/polymer-3 and https://github.com/NERDDISCO/immutability-helper/ because of ES6 modules

@midesweb
Copy link

On Polymer 2 there is another solution. It's to use "mutable-data" in the template dom-repeat.

<template is="dom-repeat" items="[[todos]]" as="todo" mutable-data>
  [[todo.completed]]
</template>

The problem i found is to notify changes to children elements of the dom-repeat. Like this:

<template is="dom-repeat" items="[[todos]]" as="todo" mutable-data>
  <todo-item todo="[[todo]]" index="[[index]]"></todo-item>
</template>

In this case <todo-item> do not change, even of the mutable-data configuration on dom-repeat. This situation is solved using the Polymer.MutableData mixin on <todo-item>.

class TodoItem extends Polymer.MutableData(ReduxMixin(Polymer.Element)) {
  // all the element code remains without changes
}

I dont know the performance of this solution. (Worried because with any minimal change in the array causes a notification of change in all the items in the dom-repeat, even if only has changed one of them)

@zakkudo
Copy link

zakkudo commented Jun 19, 2018

This worked perfect for me with immutable-js/redux, including only rending the items that have changed. FYI, I'm using Polymer 3

You need to implement helper methods for calling the immutable methods. I implemented them it as a mixin for obvious reasons....

import Immutable from 'immutable';

export default (Parent) => {
    return class ImmutableMixin extends Parent {
        _getFromImmutable(instance, key) {
            return instance.get(key);
        }
        _getInImmutable(instance, searchKeyPath) {
            return instance.getIn(searchKeyPath);
        }
        _hasFromImmutable(instance, key) {
            return instance.has(key);
        }
        _hasInImmutable(instance, searchKeyPath) {
            return instance.hasIn(searchKeyPath);
        }
        _firstFromImmutable(instance) {
            return instance.first()
        }
        _lastFromImmutable(instance) {
            return instance.last();
        }
        _toArrayFromImmutable(instance) {
            return instance.toArray();
        }
        _toObjectFromImmutable(instance) {
            return instance.toObject();
        }
    }
}

You then use these in your template to dynamically generate a shallow JS array from the immutable list, and use get or getIn if the items are immutable objects to get the values.

    static get template() {
        return html`
            <h1>Polymer with Webpack example</h1>
            <a href="#" on-click="_handleClick">Search!</a>
            <div>
            <h2>Results</h2>
            <template is="dom-if" if={{results.size}}>
                <ul>
                    <template is="dom-repeat" items="[[_toArrayFromImmutable(results)]]" as="item">
            [[Immutable.get]]
                        <li>
                            <z-toggle active="[[_getFromImmutable(item, 'active')]]" on-active-change="_handleActiveChange">[[_getFromImmutable(item, 'key')]]</z-toggle>
                        </li>
                    </template>
                </ul>
            </template>
            </div>
        `;
    }

I'm probably going to do a starter project that includes this code.

@zakkudo
Copy link

zakkudo commented Jun 28, 2018

This starter project gives an example https://github.com/zakkudo/polymer-3-starter-project

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants