简体   繁体   English

可从<button>Angular2 中的点击事件中观察到</button>

[英]Observable from <button> click event in Angular2

What's the preferred way to create an observable from a button's onclick event using Angular 2?使用 Angular 2 从按钮的 onclick 事件创建 observable 的首选方法是什么?

I'm not sure if it's considered best practice to grab the native element from the DOM in the component code (how do I do this?), or if there's some other shortcut I don't know about.我不确定从组件代码中的 DOM 中获取本机元素是否被认为是最佳实践(我该怎么做?),或者是否还有其他一些我不知道的快捷方式。

Don't overthink it.不要想太多。

@ViewChild('button') button;
clicks$:Observable<any>;

ngOnInit() {
  this.clicks$ = Observable.fromEvent(this.button.nativeElement, 'click');
}

You can use Observable.fromEvent like explained in Angular2 RxJS getting 'Observable_1.Observable.fromEvent is not a function' error您可以像Angular2 RxJS 中解释的那样使用Observable.fromEvent 获取 'Observable_1.Observable.fromEvent is not a function' 错误

Or just forward to an observable like或者只是转发到一个可观察的像

private obs = new Subject();
public obs$ = this.obs.asObservable();

@HostListener('click', ['$event']) 
clickHandler(event){
  this.obs.next(event);
}

or

<button (click)="obs.next($event)">

@Gunter's example didn't quite work for me, because my compiler didn't recognize publ . @Gunter 的示例对我来说不太适用,因为我的编译器无法识别publ

Here's an example of what worked for me: modal.component.ts这是一个对我modal.component.ts的例子: modal.component.ts

import { Output, Component } from '@angular/core';
import {Subject} from "rxjs/Subject";

export class MyModal{

    private clickStream = new Subject<Event>();

    @Output() observ = this.clickStream.asObservable();

    buttonClick(event:Event){
        this.clickStream.next(event);
    }
}

Inside modal.component.html :modal.component.html里面:

<button type="button" class="btn btn-default" (click)="buttonClick($event)">click me</button>

If you try to use @ViewChild and your button isn't visible on the page at init time (due to an *ngIf) then the assignment will be null.如果您尝试使用 @ViewChild 并且您的按钮在初始化时在页面上不可见(由于 *ngIf),则分配将为空。

You can use a setter in conjunction with @ViewChild, and run your initialization when the button first appears.您可以将 setter 与 @ViewChild 结合使用,并在按钮首次出现时运行您的初始化。

@ViewChild('btnAdd')
set btnAdd(btnAdd: Button) { ... } 

This quickly gets clumsy and inconvenient - especially if you create an observable stream from this.这很快就会变得笨拙和不方便——特别是如果你从中创建一个可观察的流。

A hybrid way might be as follows:混合方式可能如下:

btnAskAnotherClicks$ = new Subject<Event>();

<button mat-flat-button (click)="btnAskAnotherClicks$.next($event)">Ask another question...</button>

This allows you to use the click stream to create chains, but no issues if the button is initially hidden due to *ngIf.这允许您使用点击流来创建链,但如果按钮最初由于 *ngIf 被隐藏,则没有问题。

Don't like next in your template?不喜欢模板中的next Neither do I particularly.我也不特别。 But I'm ok with async , and they're both implementation details.但是我对async ,它们都是实现细节。 Well that's up to you to decide -)好吧,这由您决定-)

For those using AngularMaterial buttons and pipeable RxJS operators, some slight mods to @JoshuaDavid's answer:对于那些使用 AngularMaterial 按钮和可管道 RxJS 运算符的人,@JoshuaDavid 的回答有一些轻微的修改:

Some button in template tagged with a template variable:模板中的一些按钮用模板变量标记:

<button #btnTemplateName mat-icon-button></button>

The component code:组件代码:

import { Observable, fromEvent } from 'rxjs';

// Note importing from lettable/pipeable operators - 'operators' plural
import { tap } from 'rxjs/operators';

import { MatButton } from '@angular/material/button';

//Access the button through the template variable, typed to MatButton
@ViewChild('btnTemplateName') myBtn: MatButton;
myBtnClicks$: Observable<any>;


ngAfterViewInit() {

    // Note the need to access the native element in MatButton through the extended property chain
    this.myBtnClicks$ = 
      Observable.fromEvent(this.myBtn._elementRef.nativeElement, 'click');

    // Can now subscribe (using lettable/pipeable operators)
    this.myBtnClicks$.pipe(
       tap(() => console.log("Button clicked")),
    )
    .subscribe(event => console.log("Event:" + JSON.stringify(event)));
}

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

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