【问题标题】:Create a reusable "Loading Button" directive in Angular2在 Angular2 中创建一个可重用的“加载按钮”指令
【发布时间】:2017-02-04 21:41:30
【问题描述】:

基本上我想要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 步。我在哪里可以将我的函数绑定到点击函数上执行的事件的结尾(通常是 http 请求)?

【问题讨论】:

    标签: angular angular2-template


    【解决方案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 。然后其他服务、组件等可以请求该服务进行广播,并且您的指令会知道发生了什么,何时更改。

    【讨论】:

    • 我同意约书亚的观点。您需要将 additional info 传递给您的指令,它可以查看加载完成的时间。不过有两件事。 1)我会传递一个 Observable(不是 EventEmitter)。您可以订阅它并等待complete 事件。 2) 无需将 observable 与您的指令分开传递。您的指令也应该是输入,因此您可以编写类似&lt;div [asyncloader]="ObsToWatch"&gt; 的内容。
    • @AngularFrance,我已经能够按照 Joshua 所说的去做。您能否澄清一下我如何使用 Observables 做到这一点?谢谢。
    • @JorgeItenJr。当然,我在这里发布了一个完整的示例:stackoverflow.com/a/42041945/1153681
    • 如果可能,最好添加工作示例和答案
    【解决方案2】:

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

    @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.

    【讨论】:

      猜你喜欢
      • 2017-06-23
      • 1970-01-01
      • 2017-04-12
      • 1970-01-01
      • 1970-01-01
      • 2016-11-06
      • 1970-01-01
      • 2016-12-13
      • 1970-01-01
      相关资源
      最近更新 更多