Run componentDidUpdate only on changes within the Component

361 Views Asked by At

I'm trying to learn StencilJs and have created an "editable text" Component like this.

import { Component, h, Prop, Element } from '@stencil/core';

@Component({
  tag: 'app-input',
  styleUrl: 'app-input.scss',
  shadow: true,
})
export class AppInput {
  @Element() el: HTMLElement;
  @Prop() editMode = false;
  @Prop() value: string;

  private textInput: HTMLInputElement;
  private label: HTMLDivElement;

  componentDidUpdate() {
    if (this.textInput) {
      this.textInput.focus();
    } else {
      this.label.focus();
    }
  }

  eventHandler(event: KeyboardEvent | FocusEvent): void {
    if (event instanceof KeyboardEvent) {
      if (this.editMode) {
        if (event.code === 'Enter') {
          this.value = (event.target as HTMLInputElement).value;
          this.editMode = false;
        } else if (event.code === 'Escape') {
          this.editMode = false;
        }
      } else {
        if (['Space', 'Enter'].some(key => key === event.code)) {
          this.editMode = true;
        }
      }
    } else if (event instanceof FocusEvent) {
      this.editMode = false;
    }
  }

  render() {
    if (this.editMode) {
      return (
        <div>
          <input
            type="text"
            ref={el => this.textInput = el as HTMLInputElement}
            value={ this.value }
            onKeyDown={(event) => this.eventHandler(event)}
            onBlur={(event) => this.eventHandler(event)}></input>
        </div>
      )
    } else {
      return (
        <div
          tabindex="0"
          ref={el => this.label = el as HTMLDivElement}
          onKeyDown={(event) => this.eventHandler(event)}
          onClick={() => this.editMode = true} >{ this.value }</div>
      );

    }
  }
}

The problem is that if a parent component updates then so does this and componentDidUpdate runs, setting focus when it shouldn't. Is there a way I can tell (maybe by custom decorators) componentDidUpdate to only run if the update was triggered from within this component? Or is there another way to go about it?

0

There are 0 best solutions below