Search code examples
angularangular2-hostbindingangular2-inputs

@HostBinding initial @Input value ignored


I have a directive that helps with adding toggle effects to various elements.

export class AlloyToggleDirective {
    private toggled = false;

    @Input('alloyToggled')
    @HostBinding('class.alloy-toggled')
    get isToggled() { return this.toggled; }
    set isToggled(value: boolean) {
      this.toggled = value;
      this.alloyToggledChange.emit(this.toggled);
    }
    @Output() alloyToggledChange: EventEmitter<boolean> = new EventEmitter();

    toggle() {
      this.toggled = !this.toggled;
    }

    @HostListener('click')
    onclick() {
        this.toggled = !this.toggled;
        this.alloyToggledChange.emit(this.toggled);
    }
}

It works fine when toggled, however the initial bound value is ignored:

<button [alloyToggled]="booleanValue">

The HTML will reflect that initial value, but the class is only applied after toggling programmatically or via mouse. Is there a strange interaction when @HostBinding is on an @Input?


Solution

  • There are a few problems:

    • @Input definition

    • Variable syntax mixups

    directive.ts

    @Directive({
      selector: '[alloyToggled]'
    })
    export class HighlightDirective {
        @Input('alloyToggled') alloyToggled: boolean;
        @HostBinding('class.alloy-toggled')
        get isToggled() { return this.alloyToggled; }
        set isToggled(value: boolean) {
          this.alloyToggled = value;
          this.alloyToggledChange.emit(this.alloyToggled);
        }
        @Output() alloyToggledChange: EventEmitter<boolean> = new EventEmitter();
    
        toggle() {
          this.alloyToggled = !this.alloyToggled;
        }
    
        @HostListener('click')
        onclick() {
            this.alloyToggled = !this.alloyToggled;
            this.alloyToggledChange.emit(this.alloyToggled);
        }
    }
    

    html

    <button [alloyToggled]="booleanValue">Toggle Alloy</button>
    

    component.ts

    export class AppComponent {
      booleanValue = true;
    }
    

    HighlightDirective edited to mirror you expected code behavior. https://stackblitz.com/edit/angular-lrmveu

    Created from the Angular Highlight Example: https://stackblitz.com/angular/naavjopgege?file=src%2Fapp%2Fapp.component.html