I’ve honestly racked my brain on this for a couple days. I’m decently new to lit-element and web components in general.
Basically, I’m building a new component called <date-picker>
and it uses the Flatpickr plugin. This Date Picker component imports another component called <textfield>
. Inside of that component there is a wrapper(.date-picker) with an input field and an icon. I need to be able to access the wrapper so I can click the input field and icon to trigger the calendar popup. But no matter what I do, I can’t reach those the dom elements inside the component. I’ve tried accessing them using this.shadowRoot.querySelector('.date-picker')
along with the light dom document.querySelector('.date-picker')
among a variety of other things. Sample code below. I appreciate any insight you can offer.
Date picker component:
render() { return html` <textfield iconalt="Calendar" iconname="calendar" label="Calendar" optionaltext="hide"></textfield> `; } updated() { var datePickerShadow = this.shadowRoot.querySelector('.date-picker'); // gets el in shadow dom var datePickerLight = document.querySelector('.date-picker'); // gets el in light dom var importantDate = [Date.parse('2021-1-27'), Date.parse('2021-1-5'), Date.parse('2021-2-9')]; var datePicker = flatpickr(datePickerLight, { wrap: true, disable: ["2021-01-30", "2021-01-21", "2021-01-08", new Date(2025, 4, 9) ], allowInput: true, clickOpens: false, }) }
Advertisement
Answer
If <textfield>
is a custom element then its tagname is illegal: custom element tags must contain at least a -
. This is probably preventing the browser from upgrading it (and thus rendering its content and executing its logic).
Anyway if .date-picker
is inside of <textfield>
‘s template, neither of the querySelector
calls you tried would work: the first selects inside <date-picker>
‘s shadow dom but does not recurse in child components, while the second completely misses shadow doms.
What you can do is:
Use cascaded querySelectors
class DatePicker extends LitElement { async firstUpdated() { const textField = this.renderRoot.querySelector('text-field'); await textField.updated; // Wait for first render of text-field const datePicker = textField.renderRoot.querySelector('.date-picker'); } }
Move
.date-picker
in<date-picker>
‘s template if possiblePass
.date-picker
to<text-field>
which renders it in a slot// This way you can directly select .date-picker render() { return html` <text-field> <div class="date-picker"></div> </text-field> `; }
Instantiate the picker inside
<text-field>
and expose the instance using a property (or part of its functionality through methods and properties).
(I’d avoid the first option if possible)