angular - 如何为(单击)Angular 应用 switchMap?
问题描述
我有以下元素点击:
<div *ngFor="let doc in docs">
<app-checkbox (onSelected)="onSelectedDocument(doc, $event)" [disabled]="isApprepdocsDisabled(doc)"
[checked]="doc.isapprepdocs == 1"
[id]="doc.index"></app-checkbox>
</div>
和事件处理程序:
public closed$ = new Subject<any>();
public documentChecked$ = new Subject<any>();
ngAfterViewInit() {
this.documentChecked$
.pipe(
exhaustMap((data: { docid: number; checked: boolean }) =>
iif(
() => data.checked,
this.applicationDocumentsService.addtoappdoc(data.docid),
this.applicationDocumentsService.removefromappdoc(data.docid),
),
),
takeUntil(this.closed$),
)
.subscribe(
(res) => {
console.log(res);
},
(err) => {},
);
}
为什么在服务器错误后下一次单击不发出值?
解决方案
您可以使用 RxJSiif
函数根据条件选择可观察对象。尝试以下
public onSelectedDocument(doc: any, checked: boolean): void {
iif(
() => checked,
this.applicationDocumentsService.addtoappdoc(doc.docid),
this.applicationDocumentsService.removefromappdoc(doc.docid)
).subscribe(
res => { },
err => { }
)
}
要忽略传入事件,您需要使用exhaustMap
映射运算符。switchMap
实际上与您的要求完全相反。当发出新事件时,它将取消当前请求。
您还可以删除(click)
模板中的事件绑定并使用ViewChild
with RxJS函数从元素fromEvent
中获取click
事件。div
尝试以下
模板
<div #clickDiv>Click</div>
控制器
import { Component, OnInit, OnInit, AfterViewInit, OnDestroy, ElementRef, ViewChild } from '@angular/core';
import { iif, fromEvent, Subject } from 'rxjs';
import { takeUntil, exhaustMap } from 'rxjs';
export class SomeComponent implements OnInit, AfterViewInit, OnDestroy {
closed$ = new Subject<any>(); // <-- use to close subscriptions
@ViewChild('clickDiv', { static: false }) clickDiv: ElementRef<any>;
ngAfterViewInit() {
fromEvent(this.clickDiv.nativeElement, 'click').pipe(
exhaustMap(_ => // <-- ignore incoming events until the current event is complete
iif(
() => checked,
this.applicationDocumentsService.addtoappdoc(doc.docid),
this.applicationDocumentsService.removefromappdoc(doc.docid)
)
),
takeUntil(this.closed$)
).subscribe(
res => { },
err => { }
);
}
ngOnDestroy() {
this.closed$.next(); // <-- close open subscriptions
}
}
更新:处理来自多个 DOM 元素的事件
如果您有多个 DOM 元素,请忽略之前的更新。对于多个元素,您实际上需要使用ViewChildren
. 您可以继续使用该onSelected
事件,但您可以将事件推送到多播可观察对象(如 RxJS Subject
),而不是调用事件处理程序。然后可以使用exhaustMap
介于两者之间的操作员进行订阅。尝试以下
模板
<div *ngFor="let doc in docs">
<app-checkbox
(onSelected)="docClick$.next(doc)"
[disabled]="isApprepdocsDisabled(doc)"
[checked]="doc.isapprepdocs == 1"
[id]="doc.index"
></app-checkbox>
</div>
控制器
import { Component, OnInit, OnInit, OnDestroy } from '@angular/core';
import { iif, Subject, of } from 'rxjs';
import { takeUntil, exhaustMap, catchError } from 'rxjs';
export class SomeComponent implements OnInit, OnDestroy {
closed$ = new Subject<any>(); // <-- use to close subscriptions
docClick$ = new Subject<any>(); // <-- event handler for doc click events
ngOnInit() {
this.docClick$.asObservable().pipe(
exhaustMap(doc => // <-- ignore incoming events until the current event is complete
iif(
() => checked,
this.applicationDocumentsService.addtoappdoc(doc['docid']),
this.applicationDocumentsService.removefromappdoc(doc['docid'])
)
),
catchError(error => // <-- return valid response if error so the subscription doesn't error out
of(error)
),
takeUntil(this.closed$)
).subscribe(
res => { },
err => { }
);
}
ngOnDestroy() {
this.closed$.next(); // <-- close open subscriptions
}
}
推荐阅读
- jquery-ui - $.datepicker._curInst 如果没有从 datepicker 中选择日期,则为 null
- talend - 为什么在 tmap 中使用 addDate 不会返回正确的结果
- python - 如何加快 postgresql 中的 copy_expert?
- mongodb - 如何使用 for-loop 构建 Spring Data Mongo 聚合操作
- java - 使用 TimerGraphStageLogic 进行 Akka 流监督
- python - Python 正则表达式和在行中找到的几个命名组
- postgresql - 如何通过传递一周中的任何日期来仅检索星期四的日期
- r - R 不能识别循环中的日期
- oracle - 如何过滤 obiee 分析但小计值?
- android - 使按钮在子句上可用