Sunday, February 16, 2014

Using polymer-ajax to Load Configuration


With the first edition of Patterns in Polymer in the books, it is time to debunk everything. Well, maybe not quite everything, but I ought to keep an open mind on some of the assumptions that I made throughout so that version 1.1 of the book can be that much more solid.

The thing that sticks out the most in my mind as questionable is using <link> imports for configuration files. To be sure, there seem to be some good reasons to use them—in particular they make use of the platform. They also seem to avoid the overhead of dealing with the asynchronous nature of HttpRequest. Using <link> tags is a little messy, however. Deployment utilities do not seem to account for them and extra text content can creep in.

So it mostly works, but I am curious to see how hard HttpRequest configuration might be.

The superficial change will be that the <link> configuration:
      <hello-you>
        <link rel="import" href="hello-you.json">
        <p>And good-bye…</p>
      </hello-you>
Will change to something like:
      <hello-you conf="hello-you.json">
        <p>And good-bye…</p>
      </hello-you>
My main contention with HttpRequest based configuration is that it is a hassle. But this is Polymer, so how much of a hassle is it really? I can include an <polymer-ajax> element from the built-in Polymer elements. If I place it right in the template of my custom <hello-you> tag, I can even bind the conf attribute of <hello-you> to the url attribute of <polymer-ajax>:
<link rel="import" href="../../../packages/polymer_elements/polymer_ajax/polymer_ajax.html">
<polymer-element name="hello-you">
  <template>
    <polymer-ajax url="{{conf}}" handleAs="json"></polymer-ajax>
    <!-- ... -->
  </template>
  <script type="application/dart" src="hello_you.dart"></script>
</polymer-element>
I can also configure <polymer-ajax> to handle that resource as JSON, which I had to perform manually in my <link> approach. To listen and apply this configuration inside the backing class to <hello-you>, it is easiest to grab a reference to <polymer-ajax> and read its response attribute:
@CustomTag('hello-you')
class HelloYou extends PolymerElement {
  // ...
  @published String conf = 'packages/ajax_config/elements/hello-you.json';
  HelloYou.created(): super.created();

  ready() {
    super.ready();
    var ajax = shadowRoot.query('polymer-ajax');
    ajax.
      on['polymer-complete'].
      listen((_) {
        ajax.response.forEach((k, v)=> this[k] = v);
      });
  }
}
The polymer-complete event lets me know that a response has been received from the HttpRequest. I can then read the JSON parsed response directly from the <polymer-ajax> element's response attribute. Since the JSON response is a Map I can iterate over each key-value pair, updating the appropriate value (e.g. greeting, instructions, etc.) in <hello-you>.

And that works. If I use the specialized configuration by explicitly supplying a conf attribute to the <hello-you> Polymer, I get a specialized version of the Polymer:



But, if I remove that attribute and allow the Polymer to load the default configuration, I see:



So in the end, <polymer-ajax> does a pretty decent job of overcoming my objections to HttpRequest messiness. That said, I am not dealing with error conditions, which a <link> approach gives me for free. I am not even attempting to load default configuration and then specialized configuration at the same time here. While not something that <link> gives me for free, worries about load order are eliminated by the platform.

So I think that the <link> approach is still sound. The winning approach is not quite a clear cut as I had thought, however.


Day #1,028

No comments:

Post a Comment