2

I'm building a directive which changes a button's text while a condition remains true. For example while saving a from, until it is being processed, the text of the submit button should change to Saving... and as the form submission finished, it should revert back to its original text.

Here is a what I'm trying:

import {Directive, ElementRef, Input, OnInit} from '@angular/core';

@Directive({
  selector: '[LoadingText]'
})
export class LoadingTextDirective implements OnInit {

  @Input('loadingTextValue') text: string;
  @Input('loadingTextWhen') condition: boolean;

  constructor(private elem: ElementRef) {}

  ngOnInit() {
    if (this.text && this.condition) {
        this.elem.nativeElement.innerText = this.text;
    }
  }
}

Here is how I'm using it:

<button LoadingText loadingTextValue="Hold on! Saving..." [loadingTextWhen]="saving" type="button" (click)="onSave()">Save
                            </button>

saving: boolean = false;

I change saving to true as onSave() function is called and false as it is finished.

How can I bind my directive condition Input to reflect according to the changes on saving.?

Anuradha Gunasekara
  • 6,553
  • 2
  • 27
  • 37
Subhan
  • 1,544
  • 3
  • 25
  • 58

2 Answers2

3

You can use ngOnChanges life cycle hook by Angular to get the changes in your @Input binding.

import {Directive, ElementRef, Input, OnInit} from '@angular/core';

@Directive({
  selector: '[LoadingText]'
})
export class LoadingTextDirective implements OnInit, OnChanges {

  @Input('loadingTextValue') text: string;
  @Input('loadingTextWhen') condition: boolean;

  constructor(private elem: ElementRef) {}

  ngOnInit() {
    if (this.text) {
      if (this.condition) {
        this.elem.nativeElement.innerText = this.text;
      }
    }
  }

  ngOnChanges(changes) {
    console.log(changes.condition.currentValue);
    this.condition = changes.condition.currentValue;
    if (this.text) {
      if (this.condition) {
        this.elem.nativeElement.innerText = this.text;
      }
      else {
        this.elem.nativeElement.innerText = 'Save'
      }
    }
    // you will get changes in `@input` text here and made changes accordingly
  }
}

Working example

Pardeep Jain
  • 84,110
  • 37
  • 165
  • 215
  • 1
    `implements OnInit, OnChanges` . I know it is JavaScript at end of the day. It does not matter. But it is recommended in Angular Coding Style Guide. :) – Ritwick Dey May 21 '18 at 06:49
  • 1
    @RitwickDey, eagle eye !! Thanks dude for pointing me out , Answer Updated !! – Pardeep Jain May 21 '18 at 06:50
  • In this case, ngOnChanges is called before ngOnInit. I'm getting the initial value of the element in ngOninit but it gives undefined. – Subhan May 21 '18 at 07:44
  • @Subhan , `ngOnChanges` is always called before `ngOnInit`, So you can call some common method form both cycle hooks, if needed – Pardeep Jain May 21 '18 at 07:46
  • 1
    Thank you, I'll try. This was really helpful. – Subhan May 21 '18 at 07:48
0

you can use subject variable:

in your component HTML:

<label [loadingTextValue]="loadValue"></label>

in your component TS:

loadValue = new Subject();

changeValue() {
   this.loadValue.next('Your_Value');
}

in directive:

@Input('loadingTextValue') text: Subscription;

  constructor(
    private el: ElementRef
  ) {
  }

ngOnInit() {
    this.subscribe = this.text
      .subscribe(value => {
        this.el.nativeElement.innerText = value;
      })
  }
S. V
  • 1,085
  • 5
  • 5