Polymer: Dynamically change the stylesheet - polymer

I would like to apply some stylesheets dynamically using Polymer. The scenario is like this:
<link rel="import" href="themes/red.styles.html" />
<link rel="import" href="themes/indigo.styles.html" />
<dom-module>
<style include="indigo-styles">
<template>
<div class="header">Header</div>
<button on-click="_toggleStylesheet"></button>
</template>
</dom-module>
<script>
Polymer({
_toggleStylesheet: function () {
// remove indigo-styles and apply red-styles and so on
}
})
</script>
Does anyone know how can this be achieved in Polymer?
Thank you in advance!

Use this.updateStyles to change the style of a Polymer.Element.
Use Polymer.updateStyles to apply a change globally:
Polymer.updateStyles({
'--property-one': 'var(--paper-red-900)',
'--property-two': 'var(--paper-indigo-500)',
...
'--property-whatever': 'etc'
})

Related

How to access innerHTML of a template in the content of an element

First off, I apologize for the title-gore. I struggled to summarize this issue in a single sentence.
I have a Polymer element. In my element, I wish to display (or simply log to console) the innerHTML of a template element that is a child of (contents of) the element instance.
(Please note that the intent here is to create an element similar to the demo-snippet of iron-demo-helpers.)
Consider the following Polymer element:
<link rel="import" href="../../polymer/polymer.html">
<dom-module id="print-contents-html">
<script>
Polymer({
is: 'print-contents-html',
attached: function() {
var template = Polymer.dom(this).queryDistributedElements('template')[0];
console.log(template.innerHTML);
}
});
</script>
</dom-module>
Very simply, I query for the 'template' element and log its inner HTML.
Now consider the following usage:
<!doctype html>
<html>
<head>
<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="./print-contents-html.html">
</head>
<body>
<print-contents-html>
<template>
Hello World
</template>
</print-contents-html>
</body>
</html>
As expected, this results in "Hello World" being logged to the console.
However, I am trying to make use of the 'print-contents-html' element within another Polymer element:
<link rel="import" href="../../polymer/polymer.html">
<link rel="import" href="./print-contents-html.html">
<dom-module id="simple-demo">
<template>
<print-contents-html>
<template>
Hello World from simple demo
</template>
</print-contents-html>
</template>
<script>
Polymer({
is: 'simple-demo',
});
</script>
</dom-module>
Now if I update the usage to also include an instance of the simple-demo element:
<!doctype html>
<html>
<head>
<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="./print-contents-html.html">
<link rel="import" href="./simple-demo.html">
</head>
<body>
<print-contents-html>
<template>
Hello World
</template>
</print-contents-html>
<simple-demo></simple-demo>
</body>
</html>
I would expect to see both "Hello World" and "Hello World from simple demo" logged to the console. However the simple demo message is not logged.
It appears that while the queryDistributedElements() does return the instance of the template element, the innerHTML field is an empty string.
Does anyone know why this is the case? That accessing the content/child template element does not have its innerHTML set?
Secondly, does anyone know of an alternative method through which I can access the innerHTML of the template element that is a content/child of a polymer element?
Kind Regards,
Andrew Butler
This issue is discussed in Polymer's Github repository.
The solution is to add a preserve-content attribute it the inner <template> tag:
<dom-module id="simple-demo">
<template>
<print-contents-html>
<template preserve-content>
Hello World from simple demo
</template>
</print-contents-html>
</template>
...
Then it works!

Polymer 1.0 Extending Elements - paper-dialog with custom element

I am am trying to create a custom element that plays a youtube video in paper-dialog. So videoPlayer = Polymer.dom(this.root).querySelector('video-player'); inherits/has access to that paper-dialogs open method, I am trying to extend my custom element. It isn't working, but hopefully I am on the right track and someone can show me correctly.
I am using Polymer 1.0, but I only have https://www.polymer-project.org/0.5/docs/polymer/polymer.html#extending-other-elements to go by for extending elements.
<link rel="import" href="../bower_components/paper-dialog/paper-dialog.html">
<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../bower_components/google-youtube/google-youtube.html">
<link rel="import" href="../bower_components/polymer/polymer.html">
<dom-module id="video-player">
<template>
<div class="layout horizontal">
<paper-button dialog-dismiss>
<paper-icon-button icon="arrow-back"></paper-icon-button>
</paper-button>
</div>
<div style="height: 100%; width: 100%">
<google-youtube style="height: 100%;"
video-id="YMWd7QnXY8E"
rel="1"
start="5"
playsinline="0"
controls="2"
showinfo="0"
width="100%"
height="100%"
autoplay="1">
</google-youtube>
</div>
</template>
<script>
Polymer({
is: "video-player"
});
</script>
<paper-dialog name="video-player" extends="video-player">
<template>
<shadow></shadow>
</template>
<script>
Polymer();
</script>
</paper-dialog>
<video-player></video-player>
As was mentioned in the comments, you can't yet extend custom elements, so the existing pattern (or at least the one I use) is to make use of behaviors wherever possible and wrappers wherever not.
e.g.
<dom-module id="popup-video-player">
<template>
<video-player></video-player>
</template>
<script>
Polymer({
is: 'popup-video-player',
behaviors: [Polymer.PaperDialogBehavior],
...
});
</script>
</dom-module>
Now you can use <popup-video-player> just like a paper-dialog.
I know it stinks because if video-player has a bunch of properties that you want access to, you have to copy them in the popup-video-player element's API, which is not exactly DRY.
If you look at the paper-input source, you'll see them doing the same thing. It's obvious that they want to extend iron-input, but they can't so you get things like this:
<input is="iron-input" id="input"
aria-labelledby$="[[_ariaLabelledBy]]"
aria-describedby$="[[_ariaDescribedBy]]"
disabled$="[[disabled]]"
title$="[[title]]"
... >
As a side note, you could always hook into the <video-player>s "properties" property and make the API additions programatically.
maybe something like this would work: (untested!)
Polymer({
...
properties: (function () {
var prop = {
//special properties specific to the pop up version of video-player
//..obviously be careful to avoid name space conflicts.
};
var video_player = document.createElement('video-player');
video_player.properties.keys().forEach( function(key) {
props[key] = video_player[key];
});
return props;
}()),
});

Polymer 1.0: polymer-element not showing

The below code does not show in the browser. This works in Polymer 0.5. Is there code difference as I am using 1.0?:
<link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name="my-name">
<template>
<h1> Hello {{name}}</h1>
</template>
<script>
Polymer('my-name', {
ready: function() {
this.name = "Brown";
}
});
</script>
</polymer-element>
Basically you need to rewrite your element based on the new requirements. You can easily follow it in the migration guide, registration element section.
You should rewrite it like following:
<dom-module id="my-name">
<template>
<!--Keep in mind in polymer 1.0 you can't have whitespaces in bound tags-->
<h1>Hello <span>{{name}}</span></h1>
</template>
<script>
Polymer({
is: "my-name",
ready: function () {
this.name = "Brown";
}
});
</script>
</dom-module>
I did a Plunker where you can reproduce it.
<link rel="import" href="../bower_components/polymer/polymer.html">
<dom-module id="my-name">
<style>
/*your styles go here*/
<style>
<template>
<!-- Things to show in element view -->
<h1> Hello <span>{{name}}</span></h1>
</template>
<dom-module>
<script>
// Your script goes here
Polymer({
is: 'my-name',
properties: {
name: {
type: String,
value: 'Brown'
}
}
});
</script>
There are many differences when migrating from Polymer 0.5 to Polymer 1.0 +. They changed the old polymer-element to dom-module and name attribute to id. The constructor is also changed as i shown in the example. Read https://www.polymer-project.org/1.0/docs/migration.html to get more info on migrating.
polymer 1.0 changes <polymer-element name="my-name"> to <dom-module id="my-name">.
I think you should follow the documentation of polymer 1.0
Polymer 1.0 documentation

polymer data binding through attributes

I am trying to use data binding through attributes on Polymer but I'm just going from failure to failure. I tried many syntax to send my JSON but nothing seems to work... Can I ask a little bit of help to see and understand what i was doing wrong ?
Thanks in advance,
Here is my HTML code :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Self Tutorial 02</title>
<script src="//cdnjs.cloudflare.com/ajax/libs/polymer/0.3.4/platform.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/polymer/0.3.4/polymer.js"></script>
<link href='http://fonts.googleapis.com/css?family=Oswald:400,700' rel='stylesheet' type='text/css'>
<link rel="import" href="social-nav.html">
</head>
<body>
<social-nav social='[{"twitter":"#cyberwarfighte1"}]'></social-nav>
</body>
</html>
And here is my polymer element :
<polymer-element name="social-nav" attributes="social">
<template>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" media="screen" type="text/css" />
<div class="social-icons">
{{social}}
<template repeat="{{k in social}}">
{{k}}
</template>
</div>
</template>
<script>
Polymer('social-nav', {
});
</script>
</polymer-element>
Well, I found a way to solve my problem by myself.
For anyone who have the same problem than me, the answer is that your attribute need to be declared as an object inside the polymer element.
Here is my fixed code :
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" media="screen" type="text/css" />
<polymer-element name="social-nav" attributes="social">
<template>
<div class="social-icons">
<template repeat="{{k in social}}">
<a class="{{k.social}}" href="{{k.link}}"><i>{{k.social}}</i></a>
</template>
</div>
</template>
<script>
Polymer('social-nav', {
created: function(){
this.social = []; // <- HERE !!
}
});
</script>
</polymer-element>
And my fixed element call with the good JSON
<social-nav social="[{'social':'twitter','link':'http://twitter.com/cyberwarfighte1'}, {'social':'facebook','link':'http://facebook.com/samuel.cardillo.5'}]"></social-nav>
Hope it can help someone :)

How to use apps-global with polymer's sampler-scaffold?

I am using sample-scaffold from https://github.com/Polymer/sampler-scaffold and define some globale variables using app-globals as described in https://www.polymer-project.org/docs/polymer/polymer.html#global
like
<app-globals myvar="value"></app-globals>
<sampler-scaffold>
<core-item label="Page 1" url="page1.html"></core-item>
</sampler-scaffold>
page1.html contains also the app-globals without values.
<app-globals id="globals"></app-globals>
However, the globals element does not contain any values. Is there a way to define globals across iframes using app-globals?
What about using the Polymer Element extensions? and inheritance to keep the interface of the app-globals object static? My Plunker: http://embed.plnkr.co/uDPTVP/preview
app-config.html
<!-- per https://www.polymer-project.org/docs/polymer/polymer.html#extending-other-elements -->
<link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html">
<link rel="import" href="app-globals.html">
<polymer-element name="app-config" extends="app-globals">
<script>
Polymer({
ready: function () {
this.super();
this.values.GloabalSettingsVal1 = "GDG FTW"
}
});
</script>
</polymer-element>