Reputation: 75
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
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
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