Reputation: 21
I'm new in webcomponents with stenciljs, I'm testing creating a select, the idea with this code create and render the select:
<rhx-select label-text="A select web component">
<rhx-select-item value="1" text="option 1"/>
<rhx-select-item value="2" text="option 2"/>
</rhx-select>
The problem i have is how can i get the tags that inside my web component?
this is my code:
import { Component, h, Prop, } from '@stencil/core';
@Component({
tag: 'rhx-select',
styleUrl: 'select.css',
shadow: true,
})
export class RhxSelect {
@Prop() labelText: string = 'select-rhx';
@Prop() id: string;
@Element() el: HTMLElement;
renderOptions() {
let data = Array.from(this.el.querySelectorAll('rhx-select-item'));
return data.map((e) =>{
<option value={e.attributes.getNamedItem('value').value}>{e.attributes.getNamedItem('text').value}</option>
});
}
render(){
return (
<div>
<label htmlFor={this.id}>
{this.labelText}
</label>
<select id={this.id} class="rhx-select">
{this.renderOptions()}
</select>
</div>
)
}
}
Thank you for your time.
Upvotes: 0
Views: 699
Reputation: 4978
this.el.querySelectorAll
won't return any elements until after the component has rendered once, so that its children are available in the DOM. Therefore you will have to use something like the componentDidLoad
hook:
export class RhxSelect {
// ...
@State()
items: HTMLRhxSelectItemElement[] = [];
componentDidLoad() {
this.items = Array.from(this.el.querySelectorAll('rhx-select-item'));
}
render() {
return (
<div>
<label htmlFor={this.id}>
{this.labelText}
</label>
<select id={this.id} class="rhx-select">
{this.items.map(item => (
<option value={item.getAttribute('value')}>{item.getAttribute('text')}</option>
))}
</select>
</div>
)
}
}
Note however that componentDidLoad
is only executed once, after the component has loaded. If you want your component to support dynamic changes to the options, then you'll have to use something else, like componentDidRender
, but then you'll also have to make sure you don't end up with an infinite render loop. There's also a couple ways to solve this, by combining different lifecycle methods.
See https://stenciljs.com/docs/component-lifecycle for a list of all available lifecycle methods.
Upvotes: 0
Reputation: 8859
If you add the @Element()
decorator you can parse the children with vanilla JS:
getItems() {
return Array.from(this.el.querySelectorAll('rhx-select-item'));
}
You can then use those elements and their properties/attributes however you want, for example to generate a list of <option>
elements.
A good example is ion-select
which gets the children in the childOpts()
getter function.
A couple things to keep in mind:
display: none
watchForOptions
function.Upvotes: 0