Tuesday, January 7, 2014

Importing Per-Polymer Configuration


I had a good time updating and improving <ice-code-editor>, the Polymer version of the ICE Code Editor. I even have a nice demo page for my efforts. As cool as that was, I was unable to explore one aspect of the Polymer that I would have liked: importing config directly into the Polymer's <content>.

So tonight, I would like to see if I can import configuration into a Polymer instance. And instead of a complex Polymer that wraps a large codebase adding too many moving parts to the equation, I start with a small test case. What I am hoping to get working tonight it the ability to import configuration when using a Polymer. For a simple <hello-you> tag, that would be in the form of the usual Polymer usage plus a <link> tag inside the tag:
  <head>
    <!-- 1. Load the polyfills required to make the platform work -->
    <script src="bower_components/platform/platform.js"></script>
    <!-- 2. Load component(s) -->
    <link rel="import" href="scripts/hello-you.html">
  </head>
  <body>
    <div class="container">
      <hello-you>
        <link rel="import" href="scripts/config2.json">
      </hello-you>
    </div>
  </body>
Something that is inside a Polymer like that can be distributed into the rendered Polymer if the Polymer's template contains a <content> tag. For tonight's purposes, I stick with a version that does not include a <content> tag in the template:
<link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name="hello-you">
  <template>
    <h2>{{hello}} {{your_name}}</h2>
    <p>
      <input value="{{your_name}}">
      <input type=submit value="{{done}}!" on-click="{{feelingLucky}}">
    </p>
    <!-- ... -->
  </template>
  <script>
    Polymer('hello-you', {
      your_name: '',
      hello: 'Hello',
      done: 'Done',
      instructions: 'Introduce yourself for an amazing personalized experience!',
      feelingLucky: function() { /* ... */ }
    });
  </script>
</polymer-element>
To load the configuration, I need to add a ready() lifecycle method to this Polymer. It needs to the query the element for all <link> tags that contain JSON configuration. If there are any, it needs to parse the JSON and update the this.hello attribute for a configured greeting value. This should work:
      ready: function() {
        var links = this.
          querySelectorAll('link[rel=import]').
          array().
          filter(function(el) {
            return el.href.match(/config.*\.json/)
          });

        if (!links.length) return;

        var json = links[0].import.textContent.replace(/import/, '');
        var config = JSON.parse(json);
        if (config['greeting'] !== undefined) this.hello = config['greeting'];
      },
The only trick in there is to remove the word “import” from the text content of the <link> tag's import. I am unsure why this is there, but removing it leaves me with just the JSON, which can be parsed.

If I create a JSON config file with the following:
{
  "greeting": "Howdy"
}
Then I it works! When I load the page with my small test case, I get the configured “Howdy” greeting instead of the default “Hello”:



And, if I comment out the configuration import:
      <hello-you>
        <-- link rel="import" href="scripts/config2.json" -->
      </hello-you>

Then I get the default “Hello” greeting:



So this would seem legit! There are still some questions to answer. Most pressing is how this would work if I need to distribute nodes and import configuration. I also need to see if I can get this working in Dart. But, for a first attempt, this seems promising.


Day #989

No comments:

Post a Comment