I have a behavior that is shared across elements.
In a element i have a on-change="_toggle" switch.
In a second element i have the same code from the first element without the switch button. when the switch is active it reflect to the element containing the switch.
Q: how can i reflect the on-change="_toggle" function across all elements?
my code:
1.
<script>
LanguageBehavior = {
behaviors: [
Polymer.AppLocalizeBehavior
],
properties: {
language: {
value: 'sl',
reflectToAttribute: true
},
},
attached: function() {
this.loadResources(this.resolveUrl('/data/locales.json'));
},
_toggle: function() {
this.language = this.$.switch.checked ? 'en' : 'sl';
// This function is the problem?
}
};
</script>
2
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="../../bower_components/app-localize-behavior/app-localize-behavior.html">
<link rel="import" href="behavior.html">
<dom-module id="bazdara-element-1">
<template>
<style>
:host {
display: block;
}
</style>
{{localize('menu_2')}} // THIS CHANGES WITH THE SWITCH
<span title="english">🇬🇧 SI</span>
<paper-toggle-button on-change="_toggle" id="switch"></paper-toggle-button>
<span title="french">EN</span>
</template>
<script>
Polymer({
is: 'bazdara-element-1',
behaviors: [Polymer.AppLocalizeBehavior, LanguageBehavior],
});
</script>
</dom-module>
3
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/app-localize-behavior/app-localize-behavior.html">
<link rel="import" href="behavior.html">
<dom-module id="bazdara-element-2">
<template>
<style>
:host {
display: block;
}
</style>
{{localize('menu_2')}} // THIS Doesnt change
</template>
<script>
Polymer({
is: 'bazdara-element-2',
behaviors: [Polymer.AppLocalizeBehavior, LanguageBehavior],
});
</script>
</dom-module>
As each element will have its own copy of the behavior your approach is not going to work. Right now the only options i can come up with is:
keep both your elements in one common element and change the property there.
If you are planning to have all your elements in one single html file you can then change this feature in that html file and bind the property to all your elements.
Related
Similar to this question, Init polymer attributes before ready(), but not quite the same.
Is it possible to imperatively set attribute of a child element in Polymer before the ready event of that child element fires?
https://plnkr.co/edit/fM7lAflOLWOFuIiE7e9q?p=preview
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://polygit.org/components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="https://polygit.org/components/polymer/polymer.html" rel="import">
<link href="user-profile.html" rel="import">
</head>
<body>
<user-profile></user-profile>
</body>
</html>
user-profile.html:
<link href="https://polygit.org/components/polymer/polymer.html" rel="import">
<link href="address-card.html" rel="import">
<dom-module id="user-profile">
<template>
<address-card address$="{{address}}"></address-card>
</template>
<script>
Polymer({
is: "user-profile",
properties: {
address: {
type: String,
value: "Pass the value to the child"
}
}
});
</script>
</dom-module>
address-card.html:
<link href="https://polygit.org/components/polymer/polymer.html" rel="import">
<dom-module id="address-card">
<template>
{{content}}
</template>
<script>
Polymer({
is: "address-card",
properties: {
address: String
},
ready: function () {
alert(this.address);
}
});
</script>
</dom-module>
The element <user-profile>, pass the value {{primaryAddress}} to his child the element <address-card>. The element <user-profile> is a "mediator" that control/assing value to his child.
<dom-module id="user-profile">
<template>
…
<address-card address="{{address}}"></address-card>
</template>
…
properties: {
address: {
type: String,
value: "Pass the value to the child"
}
}
</dom-module>
In this scenario, I use the data binding system to pass the value from the parent to the child.
Linking paths with data bindings
I need to set the name of a class dynamically executing a function after an iron-ajax request.
In the template section of my element I have:
<div class="{{dynamicClass}}"></div>
I have defined this property like this:
Polymer({
is: "fila-contenido"
,
properties: {
dynamicClass: {
type: Number
}
}
...
I have an on-response function executed when iron-ajax responses:
_onResponse: function (e) {
var nro = e.detail.response.length;
switch(nro){
case 2:
this.dynamicClass = "class2";
break;
case 3:
this.dynamicClass = "class3";
break;
...
}
}
This function set the name of the class correctly.
The problem is the output is not showing the dynamic class but:
<div class="style-scope fila-contenido"></div>
How may I do this?
Thanks!
To bind to the native class attribute, use attribute binding (i.e., class$=). Otherwise, Polymer treats it as a property binding.
<div class$="{{dynamicClass}}">
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo'
});
});
<head>
<base href="https://polygit.org/polymer+1.7.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 clazz="highlight"></x-foo>
<dom-module id="x-foo">
<template>
<style>
.highlight {
color: blue;
background: lightgray;
}
</style>
<span class$="{{clazz}}">hello world</span>
</template>
</dom-module>
</body>
codepen
Considering defining a polymer element
<dom-module id="custom-element">
<template>
<h1>I expect to be green</h1>
</template>
<script>
Polymer({
is: 'custom-element',
properties: {
color: {
type: String,
value: 'red'
}
},
ready: function() {
this.style.color = this.color;
}
});
</script>
</dom-module>
I would expect that the following two would produce the same result:
(in markup)
<body>
<custom-element color="green"></custom-element>
</body>
(in JS)
var customElement = document.createElement('custom-element');
customElement.color = 'green';
document.body.appendChild(customElement);
But in fact it doesn't, as it seems that the properties are set and the polymer 'ready' function is triggered before the customElement is appended to document.body.
So basically I cannot dynamically create (in JS) custom elements and set them initial properties, different than the default properties.
How would you suggest I should do that?
Thanks!
Set the color in attached callback instead of ready. Attached is called after the element has been appended in dom.
<base href="https://polygit.org/components/">
<script src="wecomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<dom-module id="custom-element">
<template>
<h1>I expect to be green</h1>
</template>
<script>
Polymer({
is: 'custom-element',
properties: {
color: {
type: String,
value: 'red'
}
},
attached: function() {
this.style.color = this.color;
}
});
</script>
</dom-module>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
var customElement = document.createElement('custom-element');
customElement.color = 'green';
document.body.appendChild(customElement);
</script>
</body>
</html>
In your case, I would avoid altering the DOM and use a simple attribute binding.
Here is a proof of concept: http://jsbin.com/jozejemumu/1/edit?html,js,output
As you can see, I used attribute binding for the style attribute on the h1 element, which simply sets the CSS color property to whatever the value of the elements' color property is.
The code is faily simple, and looks like this:
<dom-module id="custom-element">
<template>
<h1 style$="color: [[color]];">I expect to be green</h1>
</template>
<script>
Polymer({
is: 'custom-element',
properties: {
color: {
type: String,
value: 'red'
}
}
});
</script>
</dom-module>
Using the element remains unchanged:
<custom-element color="green"></custom-element>
Or:
var customElement = document.createElement('custom-element');
customElement.color = 'orange';
document.body.appendChild(customElement);
Just make sure that the color property contains a valid HTML color name/value.
Here is my JSBin
Click on the "First Name: James" text.
I have an input element within dom-if. In an event, I am making dom-if to pass and so the element will come into existence but I cannot access the input element immediately after making the dom-if condition pass.
May be I need to know when the dom-if is actually evaluated and why the element does not exist even if the condition has become true.
<!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">
<link href="paper-input/paper-input.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<template is="dom-if" if="{{!editMode}}">
<span id="name" on-tap="_makeEditable">{{name}}: {{value}}</div>
</template>
<template is="dom-if" if="{{editMode}}">
<paper-input id="input" label="{{name}}" value="{{value}}"></paper-input>
</template>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
editMode: {
type: Boolean,
value: false
},
name: {
type:String,
value:"First Name"
},
value: {
type:String,
value:"James"
}
},
_makeEditable: function() {
this.editMode = true;
//how to find the input element here
//this.$$('#input').querySelector("input").focus();
//this.$.input.querySelector("input").focus();
}
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
This is because setting this.editMode to true does not update the DOM instantaneously.
You should be running your selector asynchronously, so that Polymer has some time to update the DOM, such as:
this.async(function() {
this.$$('#input').focus();
})
Fiddle here.
<google-map-directions map="{{map}}"
renderer-options="{{draggable:true,polylineOptions:{draggable:true,strokeColor:#000000}}}"
start-address="{{item.startAddress}}"
end-address="{{item.endAddress}}"
travel-mode="DRIVING"
waypoints='[{"location": "Palo Alto"}, {"location": "San Mateo"}]'></google-map-directions>
Is that the correct way to use the renderOptions property of the google-map-directions element? I can see any examples of how to use this option. Please provide one. My goal is to change the color of the polylines but I can not get any of the options to work.
Polymer interprets double-brackets as a data binding (and in this case, it's an invalid one):
<google-map-directions
renderer-options="{{draggable:true,polylineOptions:{draggable:true,strokeColor:#000000}}}"
... >
For Polymer to deserialize a JSON string into an object, the string must be properly formatted using JSON syntax, or else the string is taken literally. These two JSON format rules are important to remember:
The key of a member should be contained in double quotes
The value of a member must be contained in double quotes if it's a string
Using these rules, the correct version of your renderer-options would be:
<google-map-directions
renderer-options='{"draggable":true, "polylineOptions":{"draggable":true, "strokeColor":"#FF0000"}}'
... >
<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">
<link rel="import" href="google-map/google-map.html">
<link rel="import" href="google-map/google-map-directions.html">
</head>
<body>
<style>
google-map {
height: 600px;
}
</style>
<template is="dom-bind">
<google-map-directions map="{{map}}"
start-address="San Francisco"
end-address="Mountain View"
travel-mode="BICYCLING"
renderer-options='{"draggable":true, "polylineOptions":{"draggable":true, "strokeColor":"#FF0000"}}'
waypoints='[{"location": "Palo Alto"}, {"location": "San Mateo"}]'></google-map-directions>
<google-map map="{{map}}" latitude="37.779"
longitude="-122.3892"></google-map>
</template>
</body>
codepen
Note the object deserialized from the renderer-options attribute should meet the DirectionsRendererOptions object specification.
You might run into a case where the complexity of your options required an unwieldy (or unmaintainable) JSON string in your markup, in which case setting renderer-options imperatively could be a better choice:
// Declare <google-map-directions id="dir" ...> (without renderer-options attribute).
// Then, setup the options in your custom element's ready-callback.
Polymer({
is: 'x-foo',
ready: function() {
this.$.dir.rendererOptions = {
draggable: true,
polylineOptions: {
draggable: true,
strokeColor: '#FF0000'
}
};
}
});
<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">
<link rel="import" href="google-map/google-map.html">
<link rel="import" href="google-map/google-map-directions.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<style>
google-map {
height: 600px;
}
</style>
<template>
<google-map-directions id="dir" map="{{map}}"
start-address="San Francisco"
end-address="Mountain View"
travel-mode="BICYCLING"
waypoints='[{"location": "Palo Alto"}, {"location": "San Mateo"}]'></google-map-directions>
<google-map map="{{map}}" latitude="37.779"
longitude="-122.3892"></google-map>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-foo',
ready: function() {
this.$.dir.rendererOptions = {
draggable: true,
polylineOptions: {
draggable: true,
strokeColor: '#FF0000'
}
};
}
});
});
</script>
</dom-module>
</body>
codepen