I created this component to demonstrate my question. This component works in chrome and firefox, as expected. But if I write this.$.wrapper.setAttribute('class','blue');
instead of this.$.wrapper.setAttribute('class','blue style-scope poly-test');
it stops working in firefox.
Is this the preferred way to change classes on shadow dom elements inside an event handler, or am I doing something accidentally right, that might break in a future version?
Also, why do I have to specify style-scope
and my element name as a class manually for firefox?
<link rel="import" href="../js/bower_components/polymer/polymer.html">
<dom-module id="poly-test">
<style>
.blue { border: 10px solid blue; }
.red { border: 10px solid red; }
#wrapper { font-weight: bold; font-size: 42px; }
</style>
<template>
<div id="wrapper" class="red"><content></content></div>
</template>
</dom-module>
<script>
Polymer({
is: 'poly-test',
properties: {'blue': { type: 'Boolean', value: false }},
listeners: { 'click': 'clickHandler' },
clickHandler: function () {
this.blue = !this.blue;
if (this.blue) {
this.$.wrapper.setAttribute('class','blue style-scope poly-test');
} else {
this.$.wrapper.setAttribute('class','red style-scope poly-test');
}
this.updateStyles();
}
});
</script>
The idea of web components is to make the web as declarative as possible. In that spirit, the Polymer-way of implementing dynamic classes should be
Declarative approach: (https://www.polymer-project.org/1.0/docs/devguide/data-binding.html#native-binding)
...
<dom-module id="poly-test">
...
<template>
<!-- handle dynamic classes declaratively -->
<div class$="{{computeClass(isBlue)}}">
<content></content>
</div>
</template>
</dom-module>
<script>
Polymer({
is: 'poly-test',
properties: {
'isBlue': { type: Boolean, value: false }
},
listeners: { 'click': 'clickHandler' },
clickHandler: function () {
this.isBlue = !this.isBlue;
},
computeClass: function (f) {
return f ? "blue" : "red";
}
});
</script>
style-scope
is used by the framework when upgrading elements and stamping nodes into DOM (under shady behaviour I believe), and I don't think we are meant to touch it.
If you really wish to handle imperatively, I'll recommend using the Polymer API's toggleClass()
method.
Imperative approach: (http://polymer.github.io/polymer/)
...
<dom-module id="poly-test">
...
<template>
<div id="wrapper" class="red"><content></content></div>
</template>
</dom-module>
<script>
Polymer({
is: 'poly-test',
properties: {
'isBlue': { type: Boolean, value: false }
},
listeners: { 'click': 'clickHandler' },
clickHandler: function () {
this.isBlue = !this.isBlue;
this.toggleClass("blue", this.isBlue, this.$.wrapper);
this.toggleClass("red", !this.isBlue, this.$.wrapper);
}
});
</script>
Use the classList
property to manage classes:
<link rel="import" href="../js/bower_components/polymer/polymer.html">
<dom-module id="poly-test">
<style>
.blue { border: 10px solid blue; }
.red { border: 10px solid red; }
#wrapper { font-weight: bold; font-size: 42px; }
</style>
<template>
<div id="wrapper" class="red"><content></content></div>
</template>
</dom-module>
<script>
Polymer({
is: 'poly-test',
properties: {'blue': { type: 'Boolean', value: false }},
listeners: { 'click': 'clickHandler' },
clickHandler: function () {
this.blue = !this.blue;
this.$.wrapper.classList.toggle('blue', this.blue);
this.$.wrapper.classList.toggle('red', !this.blue)
}
});
</script>
More information on classList
: https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With