With Polymer how can you bind a class to the host element - polymer

I know that you can bind properties of an element to a class attribute using the syntax below for elements within a custom element,
<div id="arrow" class$="{{propertyName}}"></div>
but is it possible to apply a binding to the host element itself? I've tried what is shown below, and various other attempts but have failed!
<link rel="import" href="../bower_components/polymer/polymer.html">
<dom-module id="my-element" class$="{{propertyName}}">
<template>
<style>
</style>
</template>
<script>
Polymer({
is:'my-element'
});
</script>
</dom-module>

What you want to do is possible, by reflecting property value to attribute.
Polymer({
properties: {
someProp: {
reflectToAttribute: true
}
}
});
See below how the class and other properties' value is set on the host node.
I'm not sure though that redefining built-in properties like class is wise. If you want to use reflected properties for styling, better go for attribute selectors like I did with me-elem[other].
Polymer({
is: 'my-elem',
properties: {
class: {
reflectToAttribute: true,
value: 'red'
},
other: {
type: Boolean,
reflectToAttribute: true,
value: true
}
}
});
<!DOCTYPE html>
<html>
<head>
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import"/>
</head>
<body>
<style>
.red {
color: red;
}
my-elem[other] {
border: solid 1px black;
}
</style>
<my-elem></my-elem>
<dom-module id="my-elem">
<template>
Some text
</template>
</dom-module>
</body>
</html>
Finally, be careful with reflectToAttribute, because with large value serialized in DOM you can see a decrease in performance.

Related

Propagating CSS variables in composited elements

I've got an element (the host) that includes another element (the child).
How can I propagate the value of a CSS variable from the host to the child when the CSS variable is set on the host?
Example:
<!-- Host Element, includes <child-element> -->
<dom-module id="host-element">
<template>
<style>
child-element {
--button-color: var(--menu-button-color);
}
</style>
<child-element><child-element>
</template>
</dom-module>
<!-- Child Element, is declared within <host-element> -->
<dom-module id="child-element">
<template>
<style>
button {
color: var(--button-color);
}
</style>
<button> I should be a red button </button>
</template>
</dom-module>
And ideally I'd be able to use it like so:
<style>
host-element {
--menu-button-color: red;
}
</style>
<host-element><host-element>
Seems to be working(chrome), run the code snippet below
<!doctype html>
<head>
<base href="https://polygit.org/polymer+1.7.1/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<script>
// Setup Polymer options
window.Polymer = {
dom: 'shadow'
};
</script>
<link rel="import" href="polymer/polymer.html">
</head>
<style is="custom-style">
host-elem {
--menu-button-color: red;
}
</style>
<body>
<host-elem></host-elem>
<!-- Host Element, includes <child-element> -->
<dom-module id="host-elem">
<template>
<style>
child-elem {
--button-color: var(--menu-button-color);
}
</style>
<child-elem><child-elem>
</template>
<script>
Polymer({ is: 'host-elem'});
</script>
</dom-module>
<!-- Child Element, is declared within <host-element> -->
<dom-module id="child-elem">
<template>
<style>
button {
color: var(--button-color);
}
</style>
<button>I should be a red button </button>
</template>
<script>
Polymer({ is: 'child-elem'});
</script>
</dom-module>
</body>

Polymer sample code not working in firefox

I am trying out sample code provided by Google at https://www.polymer-project.org/1.0/start/first-element/intro.
This is what I have so far:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<script src="https://polygit.org/components/webcomponentsjs/webcomponents-lite.js"></script>
<link href="/my_components/icon-toggle-demo.html" rel="import">
</head>
<body>
<icon-toggle-demo toggle-icon="star"></icon-toggle-demo>
</body>
</html>
icon-toggle-demo.html:
<link rel="import" href="https://polygit.org/components/polymer/polymer.html">
<link rel="import" href="https://polygit.org/components/iron-icons/iron-icons.html">
<link rel="import" href="icon-toggle.html">
<dom-module id="icon-toggle-demo">
<template>
<style>
:host {
font-family: sans-serif;
};
</style>
<h3>Statically-configured icon-toggles</h3>
<icon-toggle toggle-icon="star"></icon-toggle>
<icon-toggle toggle-icon="star" pressed></icon-toggle>
<h3>Data-bound icon-toggle</h3>
<!-- use a computed binding to generate the message -->
<div><span>[[message(isFav)]]</span></div>
<!-- curly brackets ({{}}} allow two-way binding -->
<icon-toggle toggle-icon="favorite" pressed="{{isFav}}"></icon-toggle>
</template>
<script>
Polymer({
is: "icon-toggle-demo",
message: function(fav) {
if (fav) {
return "You really like me!";
} else {
return "Do you like me?";
}
}
});
</script>
</dom-module>
icon-toggle.html:
<link rel="import" href="https://polygit.org/components/polymer/polymer.html">
<link rel="import" href="https://polygit.org/components/iron-icon/iron-icon.html">
<dom-module id="icon-toggle">
<template>
<style>
/* local DOM styles go here */
:host {
display: inline-block;
}
iron-icon {
fill: rgba(0,0,0,0);
stroke: currentcolor;
}
:host([pressed]) iron-icon {
fill: currentcolor;
}
</style>
<!-- local DOM goes here -->
<!-- <span>Not much here yet.</span> -->
<!-- <iron-icon icon="polymer"> -->
<iron-icon icon="[[toggleIcon]]">
</iron-icon>
</template>
<script>
Polymer({
is: 'icon-toggle',
properties: {
toggleIcon: String,
pressed: {
type: Boolean,
value: false,
notify: true,
reflectToAttribute: true
}
},
listeners: {
'tap': 'toggle'
},
toggle: function() {
this.pressed = !this.pressed;
}
});
</script>
</dom-module>
The code works fine in chrome but I get following error in FF:
TypeError: document.registerElement is not a function
I have already included the polyfill. Something else missing?
You're doing nothing wrong. The following line in your index.html file defaults to the newest version (v1.0.0-rc.1) of the webcomponents polyfill.
<script src="https://polygit.org/components/webcomponentsjs/webcomponents-lite.js"></script>
There appears to be a bug in the current version for Firefox. The same error can also be observed in the Plunker that is linked in the Polymer docs here. This will hopefully be fixed by the Polymer team.
To fix it for now, you can explicitly use an older version. For example.
<script src="https://cdn.rawgit.com/webcomponents/webcomponentsjs/v0.7.24/webcomponents-lite.js"></script>
WebComponents v1.0.0+ should only be used with Polymer 2.0. Use version ^0.7.24 with Polymer 1.

google-map with binded api-key, combined with importHref, hides the map

This is a cross post from GitHub google-map issue #342, with more details and asking for help here.
I have a project where the Google Maps api-key is loaded with the user data through an ajax call, so I am using a dom-if waiting for the api-key to be available, as follow:
<template is="dom-if" if="[[mapikey]]" >
<google-map latitude="37.77493" longitude="-122.41942" fit-to-markers api-key="[[mapikey]]">
<google-map-marker latitude="37.777" longitude="-122.38911"></google-map-marker>
</google-map>
</template>
That approach works fine, unless in addition to set the mapikey value, the script also does some importHref() calls to load user's custom code (that's my case).
When loading a fairly large import or just a few of them (as the jsbin below), the css associated with #map changes to position:relative and the map gets hidden with height=0
element.style {
position: relative;
overflow: hidden;
}
<style>…</style>
#map.google-map {
position: absolute; <-- overwritten by element.style relative above
top: 0;
right: 0;
bottom: 0;
left: 0;
}
This is the jsbin code, also copied below for easier review
And, this is a working Url for that code.
If you click TEST-API first, you'd get and see the map as expected.
However, if your click TEST-IMPORT first, you'd get the map, but hidden, due to the change in position for the #map. Inspect the element local-dummy > google-map > div id="map" to see the changed position in thet #map element.style
p.s. If I do the importHref() calls withiin a setTimeout() with 1000 ms, then the issue goes away, but that might fail depending on the imports.
This is the full jsbin code for reproducing this issue
<!DOCTYPE html>
<html>
<head>
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="google-map/google-map.html">
<link rel="import" href="paper-button/paper-button.html">
<dom-module id="local-dummy">
<style> google-map { height:600px; } </style>
<template>
<paper-button on-click="_testImport" >Test-Import</paper-button>
<paper-button on-click="_testApi" >Test-Api</paper-button>
<template is="dom-if" if="[[mapikey]]" >
<google-map latitude="37.77493" longitude="-122.41942" fit-to-markers api-key="[[mapikey]]">
<google-map-marker latitude="37.777" longitude="-122.38911"></google-map-marker>
</google-map>
</template>
</template>
<script>
Polymer({
is: "local-dummy",
properties: {
mapikey: { notify:true }
},
_testImport: function(){
this.mapikey = "AIzaSyCib7-e6RE0e9rTDjQDjUKDLCSfKxZ3iQ4";
this.importHref("paper-material/paper-material.html",e=>console.log(e.type),e=>console.log(e.type));
this.importHref("firebase-element/firebase-collection.html",e=>console.log(e.type),e=>console.log(e.type));
this.importHref("firebase-element/firebase-document.html",e=>console.log(e.type),e=>console.log(e.type));
},
_testApi: function(){
this.mapikey = "AIzaSyCib7-e6RE0e9rTDjQDjUKDLCSfKxZ3iQ4";
}
});
</script>
</dom-module>
</head>
<body>
<local-dummy></local-dummy>
</body>
</html>
Thanks in advance for your support, Fausto
In that case since DOM is getting changed, map needs to be resized like this:
HTMLImports.whenReady(function () {
document.getElementById("map").style.height = "600px"; //ensure map container height
var map = document.querySelector('google-map');
map.resize();
});
Example
<!DOCTYPE html>
<html>
<head>
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="google-map/google-map.html">
<link rel="import" href="paper-button/paper-button.html">
<style>
</style>
<dom-module id="local-dummy">
<style>
google-map {
height: 600px;
}
</style>
<template>
<paper-button on-click="_testImport">Test-Import</paper-button>
<paper-button on-click="_testApi">Test-Api</paper-button>
<template is="dom-if" if="[[mapikey]]">
<google-map latitude="37.77493" longitude="-122.41942" fit-to-markers>
<google-map-marker latitude="37.777" longitude="-122.38911"></google-map-marker>
</google-map>
</template>
</template>
<script>
Polymer({
is: "local-dummy",
properties: {
mapikey: { notify: true }
},
_testImport: function () {
this.mapikey = "--KEY GOES HERE--";
this.importHref("paper-material/paper-material.html", e => console.log(e.type), e => console.log(e.type));
this.importHref("firebase-element/firebase-collection.html", e => console.log(e.type), e => console.log(e.type));
this.importHref("firebase-element/firebase-document.html", e => console.log(e.type), e => console.log(e.type));
HTMLImports.whenReady(function () {
var map = document.querySelector('google-map');
document.getElementById("map").style.height = "600px";
map.resize();
console.log("resized");
});
},
_testApi: function () {
this.mapikey = "--KEY GOES HERE--";
}
});
</script>
</dom-module>
</head>
<body>
<local-dummy></local-dummy>
</body>
</html>

Polymer 1.x: Imperatively accessing DOM nodes inside a dom-if template

Here is my jsBin.
I want to access by its id a DOM node inside a dom-if template. With my existing code, I expect to see true when attempting to cast these nodes to Booleans, but instead I get false (i.e., undefined).
Steps to recreate the problem:
Open this jsBin.
Understand that the HTML pane on the right is working correctly by showing Foo and Bar and not showing Baz.
Observe the console and understand the id="foo" node is accessible but the id="bar" and id="baz" elements are not. And this is my problem.
How can I access those nodes imperatively?
http://jsbin.com/kemoravote/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="iron-form/iron-form.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<div id="foo">Foo</div>
<template is="dom-if" if="{{show}}">
<div id="bar">Bar</div>
</template>
<template is="dom-if" if="{{!show}}">
<div id="baz">Baz</div>
</template>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
show: {
type: Boolean,
value: function() {
return true;
}
}
},
attached: function() {
console.log('foo', !!this.$.foo);
console.log('bar', !!this.$.bar);
console.log('baz', !!this.$.baz);
},
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
The $ selector won't work. You have to use $$ as follows:
console.log('baz', !!this.$$('#baz'));
Here is the jsBin.
http://jsbin.com/xogediyato/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="iron-form/iron-form.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<div id="foo">Foo</div>
<template is="dom-if" if="{{show}}">
<div id="bar">Bar</div>
</template>
<template is="dom-if" if="{{!show}}">
<div id="baz">Baz</div>
</template>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
show: {
type: Boolean,
value: function() {
return true;
}
}
},
attached: function() {
console.log('foo', !!this.$.foo);
console.log('bar', !!this.$.bar);
console.log('baz', !!this.$.baz);
console.log('bar', !!this.$$('#bar'));
console.log('baz', !!this.$$('#baz'));
},
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>

Polymer: Using selectors

I am using Polymer to create a web component. I want to select the div gutter when the ::host element gets the class full
<link rel="import" href="/polymer/polymer.html">
<dom-module id="smooth-header">
<style>
.full ::content gutter {
color: red;
}
</style>
<template>
<content>
<div class="gutter"></div>
</content>
</template>
<script>....</script>
</dom-module>
But I am not able to select the gutter element with the above selector.
Why should the above selector fail?
Help with an alternative to select it correctly.
You should use :host(selector) to select a class on the host element:
:host(.fill) .gutter {
color: red;
}
<head>
<base href="https://polygit.org/polymer+1.5.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<x-foo></x-foo>
<x-foo class="full"></x-foo>
<dom-module id="x-foo">
<style>
:host(.full) .gutter {
color: red;
}
</style>
<template>
<content>
<div class="gutter">
<span>{{foo}}</span>
</div>
</content>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-foo',
properties : {
foo: {
type: String,
value: "Hello world!"
}
}
});
});
</script>
</dom-module>
</body>
codepen