Polymer 1.0 Data Binding in <styles>

3.3k views Asked by At

I'm tinkering around with Polymer again and there is something I want to do but it doesn't work and the workaround looks so messy. I want to style an element but take advantage of Data Binding. Basically I try to do this:

<dom-module id="proto-element">
  <template>
    <style>
      #wrapper{
        width:{{pixels}};
        background: #e1e1e1;
      }
      #bar{
        width:80%;
      }
    </style>
   <div id="wrapper">
     <div id="bar" style$={{barStyle}}>I'm the bar! <b>{{test}}</b></div>
   </div>
  </template>
</dom-module>

<script>
Polymer({
  is: "proto-element",
  ready: function() {
    this.pixels = "300px";
    this.test = "Fear me!"
  }
});
</script>

The text bound to this.test works flawlessley. But the moustache tags that are inside of style get ignored. Is there a simple solution to this? Because using the inline style$= syntax is super messy when you are working with multiple css rules and also you always need to concatinate a string for it to work if the value you want is obtained elsewhere. Any ideas on a nice clean solution?

1

There are 1 answers

2
Michal Sukupčák On BEST ANSWER

I'm afraid what you want is (at least currently) not possible. Data-binding works only inside <template> tags, either a <template is="auto-binding"> or the template inside a <dom-module>.

In the <style> tag, data-binding simply won't work. You could try putting another <style> tag INSIDE the <template> tag (which is messy), but you still won't get the data-bound property to work, since the curly brackets {{...}} must be inside an individual tag and can't be (currently) surrounded by whitespaces (spaces, newlines, ...), see docs:

String concatenation is not supported inside a tag, and the tag can’t contain any whitespace ...

tl;dr: There are two issues that prevent you from achieving what you want: 1) Data-binding only works inside a template tag and 2) if you want to print out data-bound properties, they must be enclosed inside a html tag.

You could try a different approach:

ready: function () {
    this.$.wrapper.style.width = '300px';
}

this.$ allows you to easily access any DOM element with an id attribute (for example your #wrapper, which is accessed as this.$.wrapper) and from there, you can set any other attribute of the element (this.$.wrapper.style.width in this case).


EDIT: Also, I just noticed that you've actually put <style> tag inside the <template>, which is not advised. Since Polymer 0.8, this is the recommended structure for a custom element:

<dom-module>
    <style> ... </style>
    <template> ... </template>
</dom-module>
<script> ... </script>

Check out the Overview and Migration guide.


EDIT 2: As of Polymer 1.1 the suggested element structure (as pointed out by Max Waterman) has been updated to:

<dom-module>
    <template> 
        <style> ... </style>
        ...
    </template>
    <script> ... </script>
</dom-module>