Search code examples
angularangular2-directives

Angular 4 : Access attribute directive from host


Consider the following code :

 <button cdtSaving type="submit" class="btn btn-default" [disabled]="!canSave()">Save</button>

with cdtSaving an attribute directive :

@Directive({
  selector: '[cdtSaving]'
})
export class SavingDirective implements OnInit, OnDestroy {

  private subscription: Subscription;

  constructor(private _loaderService: LoaderService, private _elRef: ElementRef, private _renderer: Renderer2) { }

  ngOnInit() {
    // subscribe to the service state to hide/show the loader
    this.subscription = this._loaderService.loaderState
      .subscribe((state: LoaderState) => {
        this._renderer.setAttribute(this._elRef.nativeElement, 'disabled', state.show ? 'true' : null);
        console.log(`state changed:${state.show} for element ${this._elRef.nativeElement.textContent}`);
      });
  }

  ngOnDestroy() {
    // unsubscribe
    this.subscription.unsubscribe();
  }
}

Basically whenever the observable next() is called, we enable or disable the button (nativeElement).

The problem is that when setting the disabled attribute to null, the canSave method is no longer taken into account.

So instead I would like to set a flag to true/false in the directive instead of setting the disabled attribute and then I would read that flag like this :

 <button cdtSaving type="submit" class="btn btn-default" [disabled]=" cdtSaving.myFlag || !canSave()">Save</button>

Currently cdtSaving.myFlag wouldn't work but maybe there's a way to achieve that with Angular ?


Solution

  • If you want to access the directive internal state, you need to set the exportAs metadata in the @Directive() decorator.

    Also there is no need for imperative managment of the disabled attribute with ElementRef and Renderer. Just use the @HostBinding decorator.

    import {Directive, Input} from '@angular/core';
    
    @Directive({
      selector: '[cdtSaving]',
      exportAs: 'cdtSaving'
    })
    export class SavingDirective {
      myFlag = false
    }
    

    Usage:

    <button cdtSaving  #dir="cdtSaving" [disabled]="dir.myFlag">Save</button>