Multiple instances of same polymer element cause behavior on all of them
Asked Answered
O

1

5

I have this simple element which just lets you select a local file at a time, then shows selected files as items you can remove, something like this: enter image description here

The component by itself works just fine, the problem is I have another component of the same type within the same page, but inside a different parent element (and hidden). If I select n files on this first file selector, then switch to view the other parent component, this second file selector shows in it the same files selected on the first one.

If I put two of this file components in the same parent element, selecting a file in one of them doesn't show the same file in the other one, but removing a file from any of them makes the component files array property (where I store every file selected) shorter in both of them, eventually leading to being unable to remove items from one of them.

I asume my problem has to do with encapsulation in some way, but can't figure out why. This is my component's code:

<dom-module id="custom-file-input">
<style>
    ...
</style>
<template>
    <div class="horizontal layout flex relative">
        <button class="action" on-click="butclick" disabled$="{{disab}}">{{restexts.CHOOSEFILE}}</button>
        <div id="fakeinput" class="flex">
            <template is="dom-repeat" items="{{files}}" as="file">
                <div class="fileitem horizontal layout center">
                    <span>{{file.0}}</span><iron-icon icon="close" class="clickable" on-click="removeFile"></iron-icon>
                </div>
            </template>
        </div>
        <input id="fileinput" type="file" on-change="fileChanged" hidden />
    </div>
</template>
<script>
    Polymer({
        is: "custom-file-input",
        properties: {
            files: {
                type: Array,
                value: []
            },
            currentFile: {
                type: Object,
                value: {}
            },
            disab: {
                type: Boolean,
                value: false,
                reflectToAttribute: true,
                notify: true
            },
            restexts: {
                type: Object,
                value: JSON.parse(localStorage['resourcesList'])
            }
        },
        fileChanged: function (e) {
            this.currentFile = e.currentTarget.files[0];
            var elem = this;

            var fr = new FileReader();
            fr.readAsArrayBuffer(this.currentFile);
            fr.onload = function () {
                [...convert file to string64...]
                elem.push('files', [elem.currentFile.name, string64]);
            };
        },
        removeFile: function (e) {
            for (var i = 0; i < this.files.length; i++) {
                if (this.files[i] == e.model.file) {
                    this.splice('files', i, 1);
                    break;
                }
            }
        },
        butclick: function () {
            this.$.fileinput.click();
        }
    });
</script>
</dom-module>
Overact answered 6/5, 2016 at 6:32 Comment(0)
O
9

When initializing a property to an object or array value, use a function to ensure that each element gets its own copy of the value, rather than having an object or array shared across all instances of the element.

Source: https://www.polymer-project.org/1.0/docs/devguide/properties.html#configure-values

{
  files: {
    type: Array,
    value: function() { return []; }
  },
  currentFile: {
    type: Object,
    value: function() { return {}; }
  },
  restexts: {
    type: Object,
    value: function() { return JSON.parse(localStorage['resourcesList']); }
  }
}
Olmsted answered 6/5, 2016 at 7:59 Comment(1)
This is the first time I have to do such thing for something like this to work. Thank you :)Overact

© 2022 - 2024 — McMap. All rights reserved.