Anoretu
Anoretu

Reputation: 75

Polymer 2.0 Access Element Inside of Nested Template by Id

Polymer provides access to elements by id via this.$['foo']. However, I find that I am unable to access elements by id that are in nested templates.

<template>
     <vaadin-dialog id="dialog" >
          <template>
     <work-order-new  id="workordernew" on-submitted="_onWorkOrderSubmitted"> </work-order-new>
          </template>
     </vaadin-dialog>
    </template>

In this situation this.$.dialog works but this.$.workordernew does not. Are you able to access elements inside of a nested template by id and if so how?

I also tried both of approches below and they also didn't work .

Polymer.dom(this.root).querySelector():

this.$$(selector)

I saw a lot of answers for this question but none of them solved my problem.

Upvotes: 2

Views: 1086

Answers (2)

Hyyan Abo Fakher
Hyyan Abo Fakher

Reputation: 3537

In Polymer 3 , this is can be done like this

let vaadinOverlay = document.querySelector('vaadin-dialog-overlay');
let workorder = vaadinOverlay.$.content.shadowRoot.querySelector('#workorder');

Upvotes: 1

Fabio Torchetti
Fabio Torchetti

Reputation: 206

The issue you're facing is not strictly a Polymer issue, but more a reflection of what Vaadin is doing behing the scenes.

When the vaadin-dialog element is created the actual contents of the template are copied in an other element - vaadin-dialog-overlay - rather than staying in the original element.

The overlay element is inserted at the document level, so you can grab it querying for it:

let vaadinOverlay = document.querySelector('vaadin-dialog-overlay');

Once you have the overlay it's easy to get to your work-order-new element:

let workOrder = vaadinOverlay.$.content.querySelector('#workordernew');

The real question would be in this case: why are you trying to access your elements directly?

Usually, when working with components, getting to the point when you need to directly access a component is usually a good indication that there is something broken in the design of the application.

<base href="https://polygit.org/vaadin-dialog+vaadin+v1.0.0-alpha1/vaadin-button+vaadin+v1.0.0-alpha1/polymer+^2.0.0/components/">

<script src="webcomponentsjs/webcomponents-lite.js"></script>

<link rel="import" href="vaadin-dialog/vaadin-dialog.html">
<link rel="import" href="vaadin-button/vaadin-button.html">


<my-element></my-element>

<dom-module id="my-element">
  <template>
    <vaadin-dialog opened>
      <template>
        <work-order-new id="workorder"></work-order-new>
      </template>
    </vaadin-dialog>
  </template>
</dom-module>

<dom-module id="work-order-new">
  <template>
    <h4>Work Order</h4>
    <input type="text" id="inputbox" value="Default Value">
  </template>
</dom-module>

<script>
  // Extend Polymer.Element base class
  class MyElement extends Polymer.Element {
    static get is() {
      return 'my-element';
    }

    constructor() {
      super();
    }

    connectedCallback() {
      super.connectedCallback();

      /**
       * Fetch the reference to the overlay.
       **/
      let vaadinOverlay = document.querySelector('vaadin-dialog-overlay');
      
      /**
       * Fetch the reference to the `work-order-new` element.
       **/
      let workOrder = vaadinOverlay.$.content.querySelector('#workorder');

      /**
       * Wait for the overlay to be setup, this is just to show
       * that we can now use the reference to the `work-order-new`
       * element.
       **/
      setTimeout(() => {
        let inputBox = workOrder.$.inputbox;
        inputBox.value = `Changed from my-element`;
      }, 1500);
    }
  }

  customElements.define(MyElement.is, MyElement);

  class WorkOrderNewElement extends Polymer.Element {
    static get is() {
      return 'work-order-new';
    }

    constructor() {
      super();
    }

    connectedCallback() {
      super.connectedCallback();
    }
  }

  customElements.define(WorkOrderNewElement.is, WorkOrderNewElement);
</script>

Upvotes: 5

Related Questions