简体   繁体   English

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

[英]Create a reusable “Loading Button” directive in Angular2

Basically I want the same behavior described here but working in a directive, since I am going to use throughout my app.基本上我想要这里描述的相同行为但在指令中工作,因为我将在整个应用程序中使用。

So far I got this in my directive:到目前为止,我在我的指令中得到了这个:

@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;
  }
}

Steps 1 and 2 are currently working fine, my problem is in the step 3. Where Can I bind my function to the end of event executed on click function(Usually http requests)?第 1 步和第 2 步目前工作正常,我的问题出在第 3 步。在哪里可以将我的函数绑定到点击函数(通常是 http 请求)上执行的事件的结尾?

You've got two good options: 1) use an input EventEmitter 2) access case #3 via a shared singleton service.您有两个不错的选择:1) 使用输入 EventEmitter 2) 通过共享单例服务访问案例 #3。

1) would probably be best if the component using the directive has direct knowledge on when to change the text back, you'd do something like... 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");

The second option would work well if other components might want to interact with the loader in question in a more global nature.如果其他组件可能希望以更具全局性的方式与相关加载器进行交互,则第二个选项会很有效。 You'd basically do the same thing as in the first in the directive, except expose your EventEmitter from an injectable service.除了从可注入服务公开 EventEmitter 之外,您基本上会做与指令中的第一个相同的事情。 Then other services, components, whatever, could request for that service to broadcast, and your directive would know what's going on when to change.然后其他服务,组件,无论什么,都可以请求该服务广播,并且您的指令将知道发生了什么何时更改。

Just want to share with you and others my way to solve current "challenge"只想和大家分享一下我解决当前“挑战”的方法

@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: HTML:

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

Here is example where I get idea of it. 这是我了解它的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM