Saturday, August 23, 2014

Where Core-Style Global Properties Can Be Used


I am struggling with the core-style element in Polymer.dart. I can implement simple styles—both as a source and referencing them later. But I have not been able to get arguably the coolest feature working yet: setting group variables.

For instance, I might want to theme some elements with the primary color of orange. From the container page, I ought to be able to set this in a script like so:
    <script>
      CoreStyle.g.primaryColor = 'orange';
    </script>
Custom Polymer elements should then honor this primary color with settings like:
<link rel="import"
      href="../../../packages/polymer/polymer.html">
<!-- ... -->
<link rel="import"
      href="../../../packages/core_elements/core_style.html">
<polymer-element name="lorem-dialog">
  <template>
    <paper-button label="Bottom" on-tap="{{toggleDialog}}"></paper-button>
    <paper-button label="Center" on-tap="{{toggleDialog}}"></paper-button>
    <!-- ... -->
    <core-style id="theme">
      paper-button {
        border: 5px solid {{g.primaryColor}};
        padding: 2px 5px;
      }
    </core-style>
    <core-style ref="theme"></core-style>
  </template>
  <script type="application/dart" src="lorem_dialog.dart"></script>
</polymer-element>
Try as I might, I cannot get this to work. I wind up with an error about the g property not being defined:
Exception: Error evaluating expression 'CoreStyle.g.primaryColor': Class 'LoremDialog' has no instance getter 'CoreStyle'.

NoSuchMethodError: method not found: 'CoreStyle'
Receiver: Instance of 'LoremDialog'
Arguments: []
A hint from James Hurford suggests that including the script that sets the global color on the same page that defines the styles will work:
  <body>
    <h1>Play Paper</h1>

    <lorem-dialog></lorem-dialog>

    <core-style id="legacy-button">
      :host paper-button {
        border: 5px solid {{g.primaryColor}};
        padding: 2px 5px;
      }
    </core-style>
    <script>
      CoreStyle.g.primaryColor = 'orange';
    </script>
  </body>
In fact, that does work. My Polymer element can then reference the "legacy-button" core style and the buttons will have orange borders. But that does not seem right to me. I feel like I ought to set the global property in the main page and use it inside Polymer elements. I should not have to build the entire style in the containing page—the containing page then needs to know too much about the internals of my Polymer element. That defeats the purpose of encapsulating all of this stuff inside Polymer elements, does it not?

To decide which I right, I try it in JavaScript as well. And find… the same thing. In JavaScript, I do not get the exceptions that I do from Dart, but I still do not see global core styles inside Polymer element <core-style> elements:
<link rel="import"
      href="/bower_components/polymer/polymer.html">
<!-- ... -->
<link rel="import"
      href="/bower_components/core-style/core-style.html">
<polymer-element name="lorem-dialog">
  <template>
    <paper-button label="Bottom" on-tap="{{toggleDialog}}"></paper-button>
    <paper-button label="Center" on-tap="{{toggleDialog}}"></paper-button>
    <!-- ... -->
    <core-style id="theme">
      :host paper-button {
        border: 5px solid {{g.primaryColor}};
        padding: 2px 5px;
      }
    </core-style>
    <core-style ref="theme"></core-style>
  </template>
  <script>
    Polymer('lorem-dialog', {/* ... */});
  </script>
</polymer-element>
With this, I get 5px solid button borders, but the color is empty so the buttons default to black:



What I can do in the JavaScript version of Polymer that did not work in Polymer.dart is make a local copy of the g property in my sample Polymer class:
<link rel="import"
      href="/bower_components/polymer/polymer.html">
<!-- ... -->
<link rel="import"
      href="/bower_components/core-style/core-style.html">
<polymer-element name="lorem-dialog">
  <template><!-- ... --> </template>
  <script>
    Polymer('lorem-dialog', {
      created: function() {
        this.g = CoreStyle.g;
      },
      // ...
    });
  </script>
</polymer-element>
This makes the g property available inside the <template> of my Polymer element:



So am I wrong in my assumption that I should be able to set a global CoreStyle property in the containing page and use it inside elements? It sure seems that way. I have a workaround, but a workaround implies that I am working against the library, not using it as intended. So the question remains: am I doing something wrong or is core-style not meant to work like this?


Day #161


1 comment:

  1. Hi. I am also struggling this the polymer styling concept. Have you made any progress on this? Cheers Bernd

    ReplyDelete