在Angular2中创建可重用的“加载按钮”指令

时间:2017-02-04 21:41:31

标签: angular angular2-template

基本上我想要描述here所描述的相同行为但是在指令中工作,因为我将在整个应用程序中使用。

到目前为止,我在我的指令中得到了这个:

@Directive({
  selector: '[asyncLoader]'
})
export class ActionAsyncLoader {

  @Input('asyncLoader') asyncLoader: string;
  ...

  //1 - save the text for further use.
  ngOnInit(){
    this.text = this.elementRef.nativeElement.innerHTML;

  } 
  //2 - change the text when "click" is triggered
  @HostListener('click', ['$event.target']) onClick(btn) {
    btn.innerHTML = 'Loading';
  }
  //3 - change text back to the normal value
  onCallbackAsync(obj){
      this.elementRef.nativeElement.innerHTML = this.text;
  }
}

步骤1和2目前工作正常,我的问题在第3步。我在哪里可以将我的函数绑定到在click函数上执行的事件的结尾(通常是http请求)?

2 个答案:

答案 0 :(得分:1)

您有两个不错的选择: 1)使用输入EventEmitter 2)通过共享单件服务访问案例#3。

如果使用该指令的组件直接知道何时更改文本,那么

1)可能是最好的,你可以做类似......

// in your directive
@Input() changeText: EventEmitter<any>;
ngOnInit() {
    this.changeText.subscribe(event => {
        // do stuff
    });
}

// in your html
<div [asyncloader] changeText="myEventEmitter">

// and in your component
public myEventEmitter = new EventEmitter();
myEventEmitter.emit("change some text please");

如果其他组件可能希望以更全局的方式与所讨论的加载器进行交互,则第二个选项可以正常工作。除了在注射服务中公开EventEmitter之外,你基本上和指令中的第一个做同样的事情。然后,其他服务,组件,无论如何,都可以请求该服务进行广播,并且您的指令将知道何时进行更改。

答案 1 :(得分:0)

只想和大家分享我解决当前“挑战”的方法

@Directive({
  selector: '[appSpinner]'
})
export class SpinnerDirective implements OnInit, OnChanges {
  @Input() loadingState: boolean;
  contentText;

  constructor(private elem: ElementRef) {
    if (this.elem.nativeElement.innerText !== 'undefined') {
      this.contentText = this.elem.nativeElement.innerText;
    }
  }

  ngOnInit(): void {
    if (this.loadingState) {
      this.elem.nativeElement.innerHTML = '<div class="spinner-border custom-spinner-btn"></div>';
    }
  }

  ngOnChanges(changes): `void` {
    this.loadingState = changes.loadingState?.currentValue;
    if (this.loadingState) {
      this.elem.nativeElement.innerHTML = '<div class="spinner-border custom-spinner-btn"></div>';
    } else {
      if (this.contentText) {
        this.elem.nativeElement.innerText = this.contentText;
      }
    }
  }
}

HTML:

<button
      appSpinner
      [loadingState]="true"
      type="submit"
      class="btn btn-primary">
      LOGIN
    </button>

Here is example where I get idea of it.