Tayab Hussain
Tayab Hussain

Reputation: 931

Polymer 2 access file uploaded in another page

I am using a simple polymer application with few pages in iron-pages. I am uploading a file in one page and then I want to access this uploaded file in another page.

I tried several things but nothing seems to work, here is the sample code

Page in which file is uploaded

<dom-module id="file-upload-page">
    <template>
        <form method="post" enctype="multipart/form-data" action="/someation" disable-native-validation-ui no-validate>
            <my-input file={{file}} id="sampleFileInput" btn-style="primary" max-files="1" accept=".xls, .xlsx" on-drop="fileUploadChangeListener"
                label="[[localize('open_invoices_file')]]" help-text="[[localize('open_invoices_file_help')]]" no-auto required>
            </my-input>
        </form>
    </template>
    <script>
        class FileUploadPge extends Polymer.mixinBehaviors([], Polymer.Element) {
            static get is() {
                return 'file-upload-page';
            }

            static get properties() {
                return {
                }
            }
         }

         customElements.define(FileUploadPge.is, FileUploadPge);
    </script>
</dom-module>

Page in which file is accessed

<dom-module id="consumer-page">
    <template>
        //some code
    </template>

    <script>
        class ConsumerPage extends Polymer.mixinBehaviors([], Polymer.Element) {

            static get is() {
                return 'consumer-page';
            }

            constructor() {
                super();
            }

            static get properties() {
                return {
                    //some properties
                }
            }

            ready() {
                super.ready();
                var temp2 = this.$.sampleFileInput;   // returns null
                var temp3 = this.shadowRoot.querySelector("#sampleFileInput"); // returns null
                var temp4 = this.root.querySelector('#sampleFileInput'); // returns null
                var temp5 = this.$$('#sampleFileInput'); // returns null
                this._refreshSelections();

            };

            _proceed() {

                var test1 = Polymer.dom(this).querySelector("#sampleFileInput"); // returns null
                var test2 = this.$.sampleFileInput; //returns null
                var test3 = document.getElementById("sampleFileInput"); //returns null
                var test4 = this.$$("sampleFileInput"); //returns null
                var test5 = this.shadowRoot; //returns some object


                var test6 = this.$$.sampleFileInput; //returns null
                var test7 = document.querySelector('sampleFileInput'); //returns null
                var test8 = document.querySelector('file-upload-page::shadow .FileUploadPge'); //returns null
                var temp4 = this.root.querySelector('#sampleFileInput');//returns null
                var temp5 = this.$$('#sampleFileInput');//returns null
                var temp6 = this.shadowRoot.querySelector('#sampleFileInput'); // returns null
            };
        }

        customElements.define(ConusmerPage.is, ConusmerPage);
    </script>
</dom-module>

The same code works in polymer1.0 with this

document.getElementById("sampleFileInput")

Can somebody help what wrong am I doing in accessing this file in other page, and how can I handle this scenario in Polymer 2.0?

Upvotes: 0

Views: 250

Answers (1)

Umbo
Umbo

Reputation: 3142

As you said in consumer-page you're trying to access the #sampleFileInput element which is a child of another component.

All of these attempts:

var temp2 = this.$.sampleFileInput;
var temp3 = this.shadowRoot.querySelector("#sampleFileInput"); 
var temp4 = this.root.querySelector('#sampleFileInput');
var temp5 = this.$$('#sampleFileInput');
var test1 = Polymer.dom(this).querySelector("#sampleFileInput");

fail because you're trying to access an element which is not present inside consumer-page's template, while these:

var test7 = document.querySelector('sampleFileInput');
var test8 = document.querySelector('file-upload-page::shadow .FileUploadPage');

fail respectively because document.querySelector() cannot select inside shadow dom and ::shadow and /deep/ selectors were deprecated (see here).

Technically you should be able to select #sampleFileInput inside consumer-page this way:

this.parentElement // Goes back to iron-pages
    .querySelector('file-upload-page') // Selects file-upload-page
    .shadowRoot // Enters its shadow root
    .querySelector('#sampleFileInput'); // Selects the file uploader

however accessing elements inside others' shadow root is considered a not so good practice not to mention that if you're using lazy loading for iron-pages pages this will fail if file-upload-page wasn't loaded.

There are instead many other ways to expose information outside of custom elements such as events or properties.
You could, if it can fit with your implementation, use the component holding iron-pages as coordinator of your procedure and use attributes bindings to notify it with the data it needs from the different pages as the user goes on filling.

IE in file-upload-page bind the uploaded file url to a property, and observe it in the parent:

<iron-pages>
    <file-upload-page url="{{url}}"></file-upload-page>
    <consumer-page></consumer-page>
</iron-pages>

<script>
    class Parent extends PolymerElement {

        // ...

        static get properties() {
            return {
                url: {
                    type: String,
                    reflectToAttribute: true,
                    observer: '_urlChanged',
                },
            };
        }

        _urlChanged() {
            console.log(this.url);
        }

        // ...
    }
</script>

Upvotes: 3

Related Questions