Search code examples
javascriptdata-bindingpolymerimmutable.jscustom-element

Polymer data-binding and Immutable.js together


Consider the following usage of a custom polymer element

<app-header bar-foo="[[abc.def.ghi]]" app-title="[[appTitle]]"></app-header>

Here I bind two variables to the custom element app-header. Now, when I want to update the values, you might expect to do this as follows (in the parent of app-header!):

this.abc.def.ghi = 10;
this.appTitle = 'New title';

However, this only updates the appTitle not abc.def.ghi. In order to update this value as well you need to do this as follows:

this.abc = {def: {ghi: 10}};

If someone knows why this is, please let me know!!

Anyway, because of this, I would like to use Immutable! However, this introduces some issues with how data is bind to the custom elements

Here is an example snippet:

<dom-module id="my-app">
    <template>
        <app-header hits="[[state.get('page').get('hits')]]"></app-header>
    </template>
    <script>
        (function () {
            class MyApp {
                beforeRegister() {
                    this.is = 'my-app';

                    this.properties = {
                        state: {
                            type: Object,
                            notify: true,
                            value: Immutable.Map({
                                page: Immutable.Map({hits: 10})
                            })
                        }
                    };
                }
            }

            Polymer(MyApp);
        })();
    </script>
</dom-module>

So the problem occurs when binding data to an element:

<app-header hits="[[state.get('page').get('hits')]]"></app-header>

Is something like this even possible or am I doing something else completely wrong ?


Solution

  • When you update structure data, you should use the Polymer API. This will trigger the changed events and data that is bound will update. Have a look at this article on path change notification. In this case you would need to change the code to this:

    this.set('abc.def.ghi', 10);
    

    I'm not familiar with Immutable, however, this kind of expression is not supported in Polymer.

    hits="[[state.get('page').get('hits')]]"
    

    You can either bind to a (sub-) property of an element or a computing function. The computing function must be defined in your element. You can't call arbitrary functions on arbitrary objects in you data-bindings. Maybe, using the set API will eliminate the need to use Immutable.