0

What's the best way to change data between different levels (in DOM) elements?

For example, I would like to save an REST service base URL in a variable on index.html (<template is="auto-binding"), so I could access this value from anywhere in the project, regardless of the hierarchy.

I guess <core-storage> would be an option, is it? What are the other options?

Thanks

Edit:

Just found my answer here: https://stackoverflow.com/a/24876397/2750721

Community
  • 1
  • 1
Oswaldo
  • 3,296
  • 4
  • 25
  • 35

3 Answers3

2

I'd do something like what is suggested in the Polymer docs under "Supporting global variables". https://www.polymer-project.org/0.5/docs/polymer/polymer.html#global. Make an element that uses a function closure to share state between all instances of the element, then create an instance of that element any time you need access to the shared data.

Copied straight from the docs:

<polymer-element name="app-globals">
  <script>
  (function() {
    // these variables are shared by all instances of app-globals
    var firstName = 'John';
    var lastName = 'Smith';

    Polymer({
      ready: function() {
        // copy global values into instance properties
        this.firstName = firstName;
        this.lastName = lastName;
      }
    });
  })();
  </script>
</polymer-element>

Then use the element as you would any other. You can access its properties using Polymer data binding or plain JavaScript:

<polymer-element name="my-component">
  <template>
    <app-globals id="globals"></app-globals>
    <div id="firstname">{{$.globals.firstName}}</div>
    <div id="lastname">{{$.globals.lastName}}</div>
  </template>
  <script>
    Polymer({
      ready: function() {
        console.log('Last name: ' + this.$.globals.lastName);
      }
    });
  </script>
</polymer-element>
Trevor Dixon
  • 23,216
  • 12
  • 72
  • 109
2

As Trevor Dixon explained in an earlier answer you can use globals. Divshot does this for a lot of their apps (even before it was officially in the docs) but they use their own custom element for globals.

So far their is no silver bullet answer though. My experience so far is it depends on the situation as far as what is the best practice. Here are some generalizations I usually think about...

  • Global browser storage (<core-storage>, <local-forage>, pouchDB, IndexedDB, cookies, etc.)
    • Usage: this is great if you have data that you need to share with multiple elements, managing offline data, and for maintaining state/data across apps that utilize traditional browser page navigation
    • Considerations: can have limited space on client (localStorage has 5mb base as an example), usually synchronous API's (not for all though like Mozilla's localForage), limited to a single browser, can get complicated fast in maintaining state
  • Custom Events
    • Usage: great for to sharing small amounts of data and signaling across the application. Events are clean & bubble up throughout the DOM, ignoring shadow boundaries
    • Considerations: not good for large amounts of data, not optimal for Virtual DOM approaches, reliable & easy to use, limited to window & document lifecycle (refresh will not maintain data state)
  • Globals
    • Usage: Great for sharing small & large amounts of data across the app in JavaScript objects
    • Considerations: Maintenance & performance could issues if not tended to early on, Polymer has a built in mechanism for globals so it is easy to use, bound to the document & window lifecycle

Generally, no you'll use a combination of these strategies with a restful API that data is ultimately persisted to and synchronized with. this is not always the case but it is typical in modern JavaScript applications on the client.

Community
  • 1
  • 1
Erik Isaksen
  • 226
  • 2
  • 12
  • Erik and @TrevorDixon, in the 3th approach (Globals) how can I update one instance property and reflect to others instances of same element? I tried firstNameChanged: function() {firstName = this.firstName}, but didn't work – Oswaldo Mar 14 '15 at 01:35
  • @oswaldo - since this is shared data across the app the references in your element should automatically update when the values change. Here is [a codepen](http://codepen.io/Nevraeka/pen/RNqaee?editors=100). I have 2 links that change the firstName. The first link changes just the first instance of the globals and the second link changes the it on a global scale. – Erik Isaksen Mar 15 '15 at 20:48
0

You can use custom events to alert changes between multi-level element, e.g.

<component-1>
 Polymer({
   ready: function() {
    this.addEventListener("data-change", function(e) {
      this.data = e.detail.data;
    });
   },
</component-1>

<component-deep>
  Polymer({
    dataChanged: function() {
     this.fire("data-change", {data: this.data});
    }
  });
</component-deep>
flyandi
  • 1,919
  • 16
  • 25