Strange results in dom-repeat when changing array values with this.set

41 views
Skip to first unread message

Tony Mobily

unread,
Mar 15, 2017, 12:43:52 PM3/15/17
to Polymer
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>

Tony Mobily

unread,
Mar 15, 2017, 8:30:00 PM3/15/17
to Polymer
Hi,

Answering myself (and yes, thanks to StackOverflow) -- dom-repeat can't deal with native types. I changed it into objects, and it worked. 
Sorry about the noise!

Merc.
Reply all
Reply to author
Forward
0 new messages