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
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
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.
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.
I am trying to get the following to work. It initially of course renders the content of parentItems, but when changing it, the template looping over the parentItems is not invoked. I have looked at the notifyPath, but am not sure if this is the right direction
<!doctype html>
<html>
<head>
<script src='bower_components/webcomponentsjs/webcomponents-lite.min.js'></script>
<link rel='import' href='bower_components/paper-button/paper-button.html'>
</head>
<body>
<dom-module id='my-element'>
<template>
<template is='dom-repeat' items='{{parentValues}}'>
<template is='dom-repeat' items='{{item.childValues}}'>
<div>{{item.value}}</div>
</template>
</template>
<paper-button on-tap='click'>click me</paper-button>
</template>
</dom-module>
<script>
Polymer({
is: 'my-element',
properties: {
parentValues: {
type: Array,
value: function() { return [ { childValues: [ { value: 'original value' } ] } ]}
}
},
click: function() {
this.parentValues[0].childValues[0].value = 'new value';
}
});
</script>
<my-element></my-element>
</body>
</html>
How can I get it to work?
Thanks a million :-)
I believe the issue, which #jeanPokou solved was that you need to use the 'this.set(Object, New Value)' to set the value on the nested object.
You can check this video from the 'Ask Polymer' series to learn more about why it doesn't update nested values: https://youtu.be/0GxteaIaj2Q
You need to use dom-repeat with as scope in your binding, and notifyPath to bubble up change to your array when changed
<!doctype html>
<html>
<head>
<script src='bower_components/webcomponentsjs/webcomponents-lite.min.js'></script>
<link rel='import' href='bower_components/paper-button/paper-button.html'>
</head>
<body>
<dom-module id='my-element'>
<template is='dom-repeat' items='{{parentValues}}' as ="parent">
<template is='dom-repeat' items='{{parent.childValues}}' as="child">
<div>{{child.value}}</div>
</template>
</template>
<paper-button on-tap='click'>click me</paper-button>
</template>
</dom-module>
<script>
Polymer({
is: 'my-element',
properties: {
parentValues: {
type: Array,
value: function() { return [ { childValues: [ { value: 'original value' } ] } ]}
}
},
click: function() {
// notify path to the properties using the polymer syntax
this.set('parentValues.0.childValues.0.value','changed value');
}
});
</script>
<my-element></my-element>
</body>
</html>
We have a custom element that is making an AJAX call to fetch some html generated on the server side and then injected into its light dom via Polymer.dom(this).innerHTML. The response coming from the server has another custom element in it that exposes a CSS property for theming purposes. On the main page, we're setting the value for the property, but it doesn't appear to be working. How do we get Polymer to style dynamically added light DOM elements that are distributed by another element.
index.html
<style is="custom-style">
x-bar {
--mixin-property: {
background: red;
};
}
</style>
...
<body>
<x-baz>
</x-baz>
</body>
x-baz.html
<dom-module id="x-baz">
<template>
<x-foo></x-foo>
</template>
</dom-module>
<script>
Polymer({
is: "x-baz"
});
</script>
x-foo.html
<dom-module id="x-foo">
<template>
<iron-ajax auto url="..." last-response="{{response}}"></iron-ajax>
<content></content>
</template>
</dom-module>
<script>
Polymer({
is: "x-foo",
properties: {
response: {
type: String,
obeserver: 'responseChanged'
}
},
responseChanged: function(newVal)
Polymer.dom(this).innerHTML = newVal;
}
});
</script>
x-bar.html
<dom-module id="x-bar">
<style>
.elementToStyle {
#apply(--mixin-property);
}
</style>
<template>
<div class="elementToStyle">
...
</div>
</template>
</dom-module>
</script>
Polymer({
is: "x-bar"
});
</script>
The iron-ajax call returns <x-bar> ... </x-bar>.
I would expect the div inside the x-bar that comes back from the AJAX response to have a red background, but it doesn't seem to be working. What do we need to adjust to make this work correctly?
Thanks in advance!