Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

calling render() of dom-repeat after mutate the items array causes "Uncaught TypeError: Cannot read property '0' of undefined" #3022

Closed
wuyuanyi135 opened this issue Nov 19, 2015 · 3 comments
Assignees
Labels

Comments

@wuyuanyi135
Copy link

I was trying to mutate a items array of a dom-repeat with javascript and see if the template will update after the change.

This is my test code, and I host it on c9 on Nov 19, 2015.
https://myweb-wuyuanyi.c9users.io/filetable

<!DOCTYPE html>

<link rel="import" href="../polymer/polymer.html" />

<dom-module id="file-list">
    <template>
        Your files:
        <table>
            <template id="table_template" is="dom-repeat" items="{{fileItems}}">
                <tr>
                    <td>{{index}}</td>
                    <td>{{item.fileName}}</td>
                    <td>{{item.mimeType}}</td>
                </tr>
            </template>

        </table>
        <input type="button" value="Add one!" on-click="buttonClicked" />
    </template>

    <script>
        Polymer({
            is: "file-list",

            properties: {
                fileItems: {
                    value: [{
                        type: Array,
                        fileName: "filename 1",
                        mimeType: "mime 1"
                    }, {
                        fileName: "filename 2",
                        mimeType: "mime 2"
                    }],
                    notify: true
                }
            },

            buttonClicked: function() {
                //this.fileItems.push({fileName:"filename x",mimeType:"mimeType x"});
                //this.$.table_template.render();
                this.push("fileItems",{fileName:"filename x",mimeType:"mimeType x"});
            }
        });
    </script>
</dom-module>

The documentation page indicates that I need to use polymer function this.push("fileItems",object) rather than fileItems.push(object), otherwise I need manually call this.$.table_template.render() to update the template.

What happened is, when I append an object to fileItems array, the render() throws an exception

Uncaught TypeError: Cannot read property '0' of undefined
Polymer.Collection._parseKey @ polymer.html:3900
Polymer.Collection.getItem @ polymer.html:3919
Polymer._stampInstance @ polymer.html:4328
Polymer._insertInstance @ polymer.html:4338
Polymer._applyFullRefresh @ polymer.html:4201
Polymer._render @ polymer.html:4134
Debouncer.complete @ polymer.html:1231
Polymer.Base.extend.flush @ polymer-mini.html:1152
Polymer.Templatizer._flushTemplates @ polymer.html:3634
Polymer.render @ polymer.html:4129

I roughly traced the problem, and find that in function getKey in line 3883 of polymer.html, key = this.omap.get(item); was executed. But this.omap only contains 2 elements (initial value). Therefore, the new appended elements cause key to be undefined and then lead to the exception.

getKey: function (item) {
    var key;
    if (item && typeof item == 'object') {
        key = this.omap.get(item);
    } else {
        key = this.pmap[item];
    }
    if (key != undefined) {
        return '#' + key;
    }
}

Did i use the proper way to invoke render()? How can I update this.omap?

@arthurevans
Copy link

Maybe related to #3018?

@kevinpschaaf I would expect this to work, but apparently it doesn't. In v.1.2.3, it throws as described in #3018. In v1.1.5, it doesn't throw, but the wrong data is displayed.

@kevinpschaaf
Copy link
Member

This documentation is in error:

You can use the render method to force a dom-repeat to update (for example, if you’re using a third-party library that mutates the array).

Calling the render method is useful for:

  • Forcing a synchronous render of changes that have occurred to the data (this is normally batched and rendered asynchronously)
  • Re-running the filter/sort functions on the view due to changes to the filter/sort criteria

The description of any changes to the array that occurred without use of the provided array mutation API must be provided using the public notifySplices method. render() does not provide a substitute for this.

@arthurevans
Copy link

This issue was moved to Polymer/old-docs-site#1439

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants