First of all I want to thank you for your great work on hyperHTML. This is by far the most intuitive library I tried so far!
But I stumbled upon one thing and I'm not sure if I'm doing something wrong or this is just as expected.
I have to set .bind(this) on all binding methods to stay in the scope of the Web Component. Here it is the onClick attribute of the button. I expected that this is automatically done by hyperHTML and must not be set explicitly.
If I set onclick=${this.onClickToggleButton} the method (see demo code below) throws an error because it can't find this.state while called by the onClick event. Setting onclick=${this.onClickToggleButton.bind(this)} keeps the scope and everything works fine.
Could you please clearify this behavior?
Thanks in advance!
class ThemeSwitch extends HTMLElement {
constructor() {
super();
this.html = hyper.bind(this);
}
connectedCallback() {
this.state = {
open: false
};
this.render();
}
onClickToggleButton() {
this.state.open = !this.state.open;
this.render();
}
render() {
return this.html`
<div class=${`themeSwitch ${this.state.open ? 'themeSwitch--open' : ''}`}>
<button onclick=${this.onClickToggleButton.bind(this)} class="themeSwitch__toggleButton"></button>
</div>
</div>
`;
}
}
It's handled in HyperHTMLElement and hyper.Component if you use onclick=${this}: example.
Otherwise you have to track it on your own, e.g. move it into the constructor (which is a common pattern in other frameworks, e.g. React):
this.onClickToggleButton = this.onClickToggleButton.bind(this);
Or use the handleEvent() pattern.
Two answers:
If you either use HyperHTMLElement class or implement handleEvent mechanism it's easy-peasy-lemon-squeezy
class ThemeSwitch extends HTMLElement {
constructor() {
super();
this.html = hyper.bind(this);
}
handleEvent(event) {
this[`on${event.type}`](event);
}
connectedCallback() {
this.state = {
open: false
};
this.render();
}
onclick(event) {
// the button is event.currentTarget
this.state.open = !this.state.open;
this.render();
}
render() {
return this.html`
<div class=${`themeSwitch ${this.state.open ? 'themeSwitch--open' : ''}`}>
<button
onclick=${this}
class="themeSwitch__toggleButton"
/>
</div>`;
}
}
Alternatively, you can also use hyperHTML.Component which, together with HyperHTMLElement, gives you automatic state management and updates on setState.
Regards.
these questions belong and should be asked in stackoverflow so others can find answers easily :/
@sourcegr that's a very good point and I wonder if I should start labelling and closing / ignoring all questions that belongs to SO so that everyone can benefit from answers.
I believe you should have a template answer of some kind like
This is actually a usage question, please file your question in SO here.
Benefits to this are that you might actually get an answer faster and other people that have the same question will find the answer.
rephrase it in better english ;)
Also, you might want to state something like this whenever the user clicks on "new issue"...
also, you are a victim of your own kindness...
People tend to know - judging from other answers you provide - that if they ask something here, they will deftly get an answer... and a good one.
You have spoiled your users :)
where is the 馃槶 reaction ?
Thanks guys for the ultra fast feedback!!! And you're right, next time on SO... 馃憤
Most helpful comment
these questions belong and should be asked in stackoverflow so others can find answers easily :/