Reputation: 643
While going through Polymer docs, I found two ways of defining properties in custom elements, namely:
Polymer('my-element', {
myProp: 'someValue'
});
and
Polymer('my-element', {
ready: function () {
this.myProp = 'someValue';
}
});
I understand that the first one passes the object as the prototype to my custom element, so the attribute exists before the element is created, while the other one waits for the element to be initialized before declaring the property.
I am wondering what are the differences between those two (if any), and when one would use over the other? Also are there any other ways of initializing properties/functions?
Upvotes: 1
Views: 2983
Reputation: 14171
Set the default value in the created()
callback for property values that are objects or arrays. Otherwise, you can get into a "shared state" problem in your objects. Setting values inside created()
ensures that a separate object is created for each instance of the element:
<polymer-element name="my-element">
<script>
Polymer({
created: function() {
// Creates `myObj` for *this* instance.
this.myObj = {
color: 'red'
};
}
});
</script>
</polymer-element>
And I prefer put the initialization code inside created()
, rather than in ready()
. See
https://www.polymer-project.org/docs/polymer/polymer.html#lifecyclemethods for the difference between when the two callbacks fire.
To answer your other question: "Also are there any other ways of initializing properties/functions?". Yes, you can publish properties on an element. Example:
<polymer-element name="my-element">
<template>
<h1>{{val}}</h1>
</template>
<script>
Polymer({
publish: {
val: 'foo'
}
});
</script>
</polymer-element>
If you use the element like this, val
is set to "foo":
<my-element></my-element>
If you use it like this, val
is set to "bar":
<my-element val="bar"></my-element>
You can also declare attributes directly on a <polymer-element>
. These automatically get included on each instance of the element. For example:
<polymer-element name="my-element" foo="bar">
<template>
<h1 id="myHeading"></h1>
</template>
<script>
Polymer({
ready: function() {
this.$.myHeading.textContent = this.getAttribute('foo');
}
});
</script>
</polymer-element>
Note that in this case, you need to use ready()
.
And of course you can set arbitrary attributes directly on an instance of a <polymer-element>
:
<my-element disabled></my-element>
Upvotes: 4
Reputation: 905
You are correct, the first example sets the property on the prototype object. The second example, on the other hand, sets the property on an instance of the element.
In vanilla javascript, the first example will translate into this:
var F = function () {};
F.prototype.myProp = 'someValue';
While the second will translate into something similar to this:
var F = function () {
this.myProp = 'someValue';
};
It is highly recommended to avoid your first example, unless you know what you are doing. Setting properties on the prototype might have unexpected consequences. Take for example this piece of code:
Polymer('my-element', {
myConfig: {
myProp: 'someValue'
}
});
var el1 = document.createElement('my-element'),
el2 = document.createElement('my-element');
el1.myConfig.myProp = 'anotherValue';
console.debug(el2.myConfig.myProp); // will output 'anotherValue'
You can see that even though I am printing el2.myConfig.myProp
, it is the same value as set on el1.myConfig.myProp
. This happens due to the nature of Prototypal Inheritance.
Upvotes: 1