Angular @HostListener 如果不使用默认值,则延迟点击直到给出输入
Angular @HostListener delay click until input is given if not use default values
我正在努力完成这项工作。
我想要实现的是以下内容。
我有一个带有该指令检查的属性输入的指令,但如果没有给出输入,它会使用指令本身定义的一些默认值。
但是点击处理本身总是在输入值到达之前发生。所以它总是检查错误的输入(默认输入)。
我也尝试过使用一些 rxjs,但有些东西不对劲。
该指令看起来像这样。
如果我登录 exceptions
@Oninit
订阅,它甚至不会记录任何内容。
我如何调整我的指令以使其在需要时工作?
一些代码可以更好地理解
private onChangeSub$ = new Subject<AutoSaveExceptions>();
private readonly clicks$ = new Subject<HTMLElement>();
private someStream$: Subscription;
private subscription$: Subscription;
ngOnChanges(changes: SimpleChanges) {
if (changes && changes['exceptions'] && changes['exceptions'].firstChange === true) {
this.onChangeSub$.next(changes['exceptions'].currentValue);
console.log(changes['exceptions'].currentValue);
}
}
ngOnInit() {
console.log('oninit');
this.subscription$ = this.onChangeSub$.pipe(
defaultIfEmpty(this.inlineDefaultExceptions)
).subscribe((exceptions) => {
this.exceptionAttributes = exceptions;
});
this.someStream$ = this.clicks$.pipe(
delay(300),
).subscribe((target) => this.handleClicks(target));
}
@HostListener('document:click', ['$event.target'])
onClick(target: HTMLElement) {
this.clicks$.next(target);
}
Operator defaultIfEmpty()
在其源 Observable 完成时发出。但是,您的 onChangeSub$
是一个只有在您调用 onChangeSub$.complete()
时才会完成的主题,因此您永远不会收到默认值。
您可能正在寻找这样的东西:
timeoutWith(delay, of(this.inlineDefaultExceptions))
首先,一般情况下必须避免使用@HostListener('document:click', ['$event.target'])
。这可能成为主要性能问题的根源。原因是你的每个 directive/component 实例都注册了与你拥有的 directive/component 实例一样多的文档点击,所有这些实例都会严重触发更改检测。小心那个。
如果你想听全局点击,你应该做的是这样的:
const documentClick$: Observable<MouseEvent> = fromEvent(document, 'click').pipe(publish(), refCount());
export const DOCUMENT_CLICK = new InjectionToken('DOCUMENT_CLICK', {providedIn: 'root', factory: () => documentClick$});
然后将其注入您的 component/directive:
constructor(@Inject(DOCUMENT_CLICK) private readonly documentClick$: Observable) {}
然后你可以用它做任何类型的 rxjs 魔法,它会确保你在整个应用程序中最多只有一个文档点击监听器。更少的变化检测 运行 - 更好的性能。
现在您可以过滤您的 click$ 流,直到您做出更改:
this.documentClick$.pipe(
withLatestFrom(this.onChangeSub$) // should not emit anything further until this stream emits, if it does, just add a filter
filter(([event, changes]) => ... ) // check that it's not default
).subscribe(() => ...) // handle there for example
编辑:
您的指令可以检查编辑状态并注入 elementRef
和我上面提到的 documentClick$
,然后当启用编辑时指令可以监听全局点击并以检查它是否在我们元素之外的方式处理它,并且如果是这样触发将导致自动保存的事件。
这里是stackblitz link。
我正在努力完成这项工作。 我想要实现的是以下内容。
我有一个带有该指令检查的属性输入的指令,但如果没有给出输入,它会使用指令本身定义的一些默认值。 但是点击处理本身总是在输入值到达之前发生。所以它总是检查错误的输入(默认输入)。 我也尝试过使用一些 rxjs,但有些东西不对劲。 该指令看起来像这样。
如果我登录 exceptions
@Oninit
订阅,它甚至不会记录任何内容。
我如何调整我的指令以使其在需要时工作?
一些代码可以更好地理解
private onChangeSub$ = new Subject<AutoSaveExceptions>();
private readonly clicks$ = new Subject<HTMLElement>();
private someStream$: Subscription;
private subscription$: Subscription;
ngOnChanges(changes: SimpleChanges) {
if (changes && changes['exceptions'] && changes['exceptions'].firstChange === true) {
this.onChangeSub$.next(changes['exceptions'].currentValue);
console.log(changes['exceptions'].currentValue);
}
}
ngOnInit() {
console.log('oninit');
this.subscription$ = this.onChangeSub$.pipe(
defaultIfEmpty(this.inlineDefaultExceptions)
).subscribe((exceptions) => {
this.exceptionAttributes = exceptions;
});
this.someStream$ = this.clicks$.pipe(
delay(300),
).subscribe((target) => this.handleClicks(target));
}
@HostListener('document:click', ['$event.target'])
onClick(target: HTMLElement) {
this.clicks$.next(target);
}
Operator defaultIfEmpty()
在其源 Observable 完成时发出。但是,您的 onChangeSub$
是一个只有在您调用 onChangeSub$.complete()
时才会完成的主题,因此您永远不会收到默认值。
您可能正在寻找这样的东西:
timeoutWith(delay, of(this.inlineDefaultExceptions))
首先,一般情况下必须避免使用@HostListener('document:click', ['$event.target'])
。这可能成为主要性能问题的根源。原因是你的每个 directive/component 实例都注册了与你拥有的 directive/component 实例一样多的文档点击,所有这些实例都会严重触发更改检测。小心那个。
如果你想听全局点击,你应该做的是这样的:
const documentClick$: Observable<MouseEvent> = fromEvent(document, 'click').pipe(publish(), refCount());
export const DOCUMENT_CLICK = new InjectionToken('DOCUMENT_CLICK', {providedIn: 'root', factory: () => documentClick$});
然后将其注入您的 component/directive:
constructor(@Inject(DOCUMENT_CLICK) private readonly documentClick$: Observable) {}
然后你可以用它做任何类型的 rxjs 魔法,它会确保你在整个应用程序中最多只有一个文档点击监听器。更少的变化检测 运行 - 更好的性能。
现在您可以过滤您的 click$ 流,直到您做出更改:
this.documentClick$.pipe(
withLatestFrom(this.onChangeSub$) // should not emit anything further until this stream emits, if it does, just add a filter
filter(([event, changes]) => ... ) // check that it's not default
).subscribe(() => ...) // handle there for example
编辑:
您的指令可以检查编辑状态并注入 elementRef
和我上面提到的 documentClick$
,然后当启用编辑时指令可以监听全局点击并以检查它是否在我们元素之外的方式处理它,并且如果是这样触发将导致自动保存的事件。
这里是stackblitz link。