Switching themes with Polymer <core-style> - polymer

I'm unsure of the most idiomatic way to use Polymer's <core-style> to switch user-selected CSS themes. Right now I'm doing this:
<template if="{{ theme == 'theme-grey'}}">
<core-style ref="theme-grey"></core-style>
</template>
<template if="{{ theme == 'theme-blue'}}">
<core-style ref="theme-blue"></core-style>
</template>
<template if="{{ theme == 'theme-red'}}">
<core-style ref="theme-red"></core-style>
</template>
Where the producers are brought in via imports. This works ok but it seems a little wordy. I had imagined doing something like this:
(doesn't work)
<core-style id="theme" ref="theme-red"></core-style>
...
themeChanged: function(oval, nval) {
this.$.theme.ref = nval;
}
I guess that doesn't work because you can't set both ref and id, and looking over the <core-style> source I'm not sure that ref is intended to be changed dynamically. So is the template block the correct approach? Thanks.
Edit: this doesn't seem to work either:
<core-style ref="{{theme}}"></core-style>

Related

How to reference a polymer component from auto-binding template?

How to reference the ts component from a binding annotation in an auto-binding template, as in {{ts.value}} shown below:
<template is="dom-bind">
<tri-state id='ts' value="open"></tri-state>
Value: {{ts.value}}
</template>
Figured out how to do this. Just imagine that the auto-binding template has a property called x (for example) and bind both things to x like this:
<template is="dom-bind">
<tri-state value="{{x}}"></tri-state>
Value: {{x}}
</template>

Polymer 1.0: Conditional Flow statements

Can I do something like the following, in Polymer 1.0:
<template is="dom-bind">
<template is="dom-if" if="{{ messagetype=='chat' }}">
<p>{{message.text}}</p>
</template>
<template is="dom-if" if="{{ messagetype=='location' }}">
<p>{{message.latitude}} , {{message.longitude}}</p>
</template>
</template>
i.e make a decision based on messagetype binding and write nothing else in Polymer() function
Expression syntax in Polymer 1.0 is very limited.
You can access fields (or propeeties) and functions.
The expression can use ! for not and . for . for array index and object property access.
For everything esle create a function that returns the computed result.
See also https://www.polymer-project.org/1.0/docs/devguide/data-binding.html#expressions-in-binding-annotations
For your example you could create a function like
function: isEqual(a, b) {
return a == b;
}
and use it in the binding like
<template is="dom-if" if="{{isEqual(messagetype, 'chat')}}">
This is not a good use of dom-if statements. You are better off creating a function that computes what text to put into the p tag and moving the conditional logic into there.
Something along the lines of this:
<template is="dom-bind">
<p>[[computeMessageValue(message, messagetype)]]</p>
</template>
With the following computing function:
computeMessageValue: function (message, messagetype) {
if (messagetype === 'chat') {
return message.text;
} else if (messagetype === 'location') {
return message.latitude + ' , ' + message.longitude;
}
}
Using the dom-if approach is slower, harder to write tests for and gets very messy very quick as you add in new message types.

Conditional template on Polymer 1.0

I'm having trouble applying the new conditional template, in particular with the condition itself, I think.
I've got something like this:
<template is="dom-repeat" items="{{menuitems}}" as="poscol">
<template is="dom-if" if="{{index != 4}}">
<div class="positioncolum horizontal layout center wrap flex">
<span>{{index}}</span>
<template is="dom-repeat" items="{{poscol}}" as="mitem" >
<main-menu-item mitem="{{mitem}}"
order="{{mitem.TotalOrder}}"
onclick="clickMainMenuMod(index)">
</main-menu-item>
</template>
</div>
</template>
</template>
Now, if I comment the <template is="dom-if" if="{{index != 4}}"> bit it works fine, the index shows as it should.
On the fourth array are stored modules that the user has selected as non-visible, so they shouldn't appear on the main menu.
I guess there's something wrong with the if condition, but I can't guess what.
Thanks!
Try to modify your conditional template like this:
<template is="dom-if" if="{{show(index)}}">
And add this function to Polymer script:
show: function (index) {
return index != 4;
}

Polymer: How do you create repeating elements dynamic?

I have a Polymer element called edit-box that acts as a container for a set of unspecified elements based on incoming data.
<link rel="import" href="/assets/bower_components/polymer/polymer.html">
<link rel="import" href="/assets/elements/field-text.html">
<link rel="import" href="/assets/elements/field-hidden.html">
<polymer-element name="edit-box" attributes="dataFields">
<template>
<template repeat="{{dataField in dataFields}}">
<field-{{dataField.Type}}></field-{{dataField.Type}}>
</template>
<input type="button" value="Save" />
</template>
<script>
Polymer('edit-box', {
...
}
</script>
</polymer-element>
dataField.Type might be "text" or "hidden", etc.
I have created other polymer elements called field-text and field-hidden, etc.
This is just the basic idea, I know it's not polished. How can I go about looping through my dataFields and render different elements within this edit-box container element based on what exists inside of that data set?
It would be super cool to bind to an element name like this, but it's not possible. Polymer's internal Node.bind() library needs a property, TextNode, etc. to bind to. In the case of <field-{{dataField.type}}>, the {{}} is meaningless, as there's nothing to latch on to.
One way you can achieve what you want is to use conditional templates:
<template repeat="{{dataField in dataFields}}">
<template if="{{dataField.type == 'text'}}">
<field-text></field-text>
</template>
<template if="{{dataField.type == 'chart'}}">
<field-chart></field-chart>
</template>
</template>
http://jsbin.com/yuqinoxa/1/edit
Even better would be to create a generic element, and give it a type attribute to bind to:
<template repeat="{{dataField in dataFields}}">
<field-element type="{{dataField.type}}"></field-element>
</template>
http://jsbin.com/tirokuso/1/edit

Caching elements in templates

I have my main element using the flatiron-element to redirect my user:
....
<template if="{{route != null}}">
<template if="{{route == 'home' || route == ''}}">
<home-element structure="{{home}}"></home-element>
</template>
<template if="{{route == 'research'}}">
<research-element structure="{{research}}"></research-element>
</template>
<template if="{{route == 'highlights'}}">
<!-- <highlights-element></highlights-element> -->
</template>
</template>
....
Each time I change {{route}}, the elements get recreated. Is there a good way to cache it so we do not have to reload it if it was previously loaded?
Thanks
What you're seeing is Polymer's template system instantiating each element as needed. When you cycle routes, it adds/removes the element from the DOM. The next time a round, the data-binding system stamps out a new instance of the element. This also means created() and ready() get called "again".
One option is to use <polymer-ui-pages> for this: http://www.polymer-project.org/docs/elements/polymer-ui-elements.html#polymer-ui-pages
Another is to show/hide elements as needed in CSS (instead of using conditional templates): http://jsbin.com/zeyoyisu/2/edit