I am trying to improve an existing module so that I can send a nice PR to them. However, I am getting stuck.
Basically, when I try to change the values of the _stars array using this.set('_stars.' + i, value )
, dom-template seems to display things in a seemly random fashion.
The module's original author solved the problem by reassigning the whole array. At the beginning I though that they must have ignored Polymer's ability to change index values of an array. Now I wonder if they encountered the same type of weirdness...
If you use the original _updateStars
, you will see that nothing works. Using the one marked as __updateStars
, everything works precisely as expected.
The weirdness must have a pattern, but I couldn't work it out.
Please tell me I am missing something obvious!
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../paper-icon-button/paper-icon-button.html">
<link rel="import" href="../iron-icons/iron-icons.html">
<link rel="import" href="../iron-icon/iron-icon.html">
<dom-module id="star-rating">
<template>
<style>
iron-icon {
color: var(--star-color, #4775D1);
}
paper-icon-button {
color: var(--star-color, #4775D1);
--paper-icon-button-disabled: {
color: #4775D1;
};
}
[score] {
@apply(--layout-horizontal);
@apply(--layout-center);
}
</style>
<div score>
HERE: {{_o(_stars,_stars.*)}} EH
<template id="domRepeat" is="dom-repeat" items="{{_stars}}" as="star">
{{star}}
<template is="dom-if" if="[[readOnly]]">
<iron-icon icon="{{star}}"></iron-icon>
</template>
<template is="dom-if" if="[[!readOnly]]">
<paper-icon-button id="item-{{index}}" on-click="_updateRate" icon="{{star}}"></paper-icon-button>
</template>
</template>
<template is="dom-if" if="[[readOnly]]">
<content select='[votes]'></content>
</template>
</div>
</template>
<script>
Polymer({
_o: function(o ){
return JSON.stringify( o );
},
is: "star-rating",
observers: [
'_updateStars(rate)'
],
properties: {
_stars: {
type: Array,
value: function() { return ["star", "star", "star-half", "star", "star-border"]; },
},
// number of stars assigned for score
rate: {
type: Number,
value: 0
},
// show votes and disble scoring option
readOnly: {
type: Boolean,
value: false
}
},
_updateRate: function (e) {
var id = parseInt( e.currentTarget.id.split('-')[1] );
this.rate = id + 1;
},
_updateStars: function (rate) {
var intPart = Math.floor(rate);
var decimalPart = rate % 1;
debugger;
for (var i = 0; i < 5; i++) {
this.set('_stars.' + i, (i < intPart) ? 'star' : 'star-border' ) ;
}
if (decimalPart >= 0.5) this.set('_stars.' + intPart, "star-half" );
},
__updateStars: function (rate) {
var intPart = Math.floor(rate);
var decimalPart = rate % 1;
debugger;
for (var i = 0; i < 5; i++) {
//this.set('_stars.' + i, (i < intPart) ? 'star' : 'star-border' ) ;
this._stars[ i ] = (i < intPart) ? 'star' : 'star-border' ;
}
if (decimalPart >= 0.5) this._stars[ intPart ] = "star-half";
var array = this._stars;
this._stars = [];
this._stars = array;
},
});
</script>
</dom-module>
The __updateStars
function works because you are creating new array and notifies Polymer's that a change has happen, and dom-repeat
do their job.
_updateStars
function doesn't work because:
Primitive array items are not supported. This is because primitives (like number, string and boolean values) with the same value are represented by the same object.
Here you can find a short explanation about working with arrays. This is in Polymer 1.0