Wednesday, January 8, 2014

Day 990: Internal Configuration of Polymers


The line between configuration and attributes is a fine one. For Polymer elements I offer the number 6 as the dividing line. If a Polymer supports more than 6 attributes, then it seems ugly to jam them into a list of HTML attributes.

Even when configuration is used, defaults can reside in the Polymer definition as attributes:
    Polymer('hello-you', {
      hello: 'Hello',
      done: 'Done',
      instructions: 'Introduce yourself for an amazing personalized experience!',
      // ...
    });
That will work just fine even if the Polymer supports importing external configuration as I established last night in form of <link> imports:
      <hello-you>
        <link rel="import" href="scripts/hello-you.json">
      </hello-you>
But I like the idea of using the same configuration file internally in the Polymer as is supported when using the Polymer. To do that, I can use a similar <link> import trick, only the access is slightly different than last night.

First things first, I include the internal configuration in the same place that I include the Polymer library itself—outside of the <polymer-element> definition:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="_hello-you.json">
<polymer-element name="hello-you">
  <template>
    <!-- ... -->
  </template>
  <script>
    Polymer('hello-you', {
      // ...
    });
  </script>
</polymer-element>
Now, inside the Polymer class, I can load the internal configuration before the external configuration, which allows the external configuration, if specified, to take precedence:
    Polymer('hello-you', {
      // ...
      ready: function() {
        this._loadConfig();
        this._loadCustomConfig();
      },
      // ...
    });
As for reading the internal _hello-you.html configuration file, I figured out how to do that when I was mucking around with internationalization. I can query for the <link> tags in the Polymer definition through the element property:
    Polymer('hello-you', {
      // ...
      ready: function() {
        this._loadConfig();
        this._loadCustomConfig();
      },

      _loadConfig: function() {
        var links = this.
          element.
          parentElement.
          querySelectorAll('link[rel=import]').
          array().
          filter(function(el) {
            return el.href.match(/_hello-you.json/)
          });

        if (!links.length) return;

        var json = links[0].import.textContent.replace(/import/, '');
        var config = JSON.parse(json);

        for (var prop in config) {
          this[prop] = config[prop];
        }
      },
      // ...
    });
The only trick remains to remove the work “import” from the <link> tag's text content.

With that, I have an internal configuration for my Polymer. If I define the default, internal configuration in _hello-you.json as:
{
  "hello": "[Default] Hello",
  "done": "[Default] Done",
  "instructions": "[Default] Introduce yourself for an amazing personalized experience!"
}

Then my Polymer, in lieu of a custom configuration, looks like:



If I add a custom configuration when I use the Polymer:
      <hello-you>
        <link rel="import" href="scripts/hello-you.json">
      </hello-you>
Then I get my customized Polymer:



This small example file is probably overkill for configuration. As I said, the dividing line is probably somewhere around 6 attributes that would need to go in the configuration JSON file. But this seems to work nicely. There are still a few questions left to answer, but this vein of exploration continues to look promising. I will pick back up tomorrow night to see if the external configuration will work even when I want to use the <content> tag to distribute content.


Day #990

No comments:

Post a Comment