Hyperhtml: Loosing this-scope inside Web Component

Created on 3 Jul 2018  路  8Comments  路  Source: WebReflection/hyperHTML

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>
`;
    }
}
invalid question

Most helpful comment

these questions belong and should be asked in stackoverflow so others can find answers easily :/

All 8 comments

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:

  1. have a look at HyperHTMLElement which simplifies your life in many ways
  2. hyperHTML doesn't do anything different than what DOM would do. If you set a listener to a DOM node you either use handleEvent or you need to bind that listener.

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... 馃憤

Was this page helpful?
0 / 5 - 0 ratings