根据条件订阅 Observable
Subscribing to an Observable based on conditions
背景
我使用的 Reactive Forms 扩展了两个选项卡(页面的前半部分只有选项卡),然后是底部带有提交按钮的长页面。我在单击“提交”按钮时进行验证。
单击“提交”按钮后,如果验证失败,页面需要滚动到错误表单字段。
我还可以根据 FormGroups 中的错误加载选项卡。
问题
- 滚动发生在选项卡加载之前。
- 为了解决第 1 点,我订阅了 animationDone 事件,然后滚动到其中的点。
submit(){
//code to select the desired tab
this.selectedTab.animationDone.subscribe(res => {
this.myElement.nativeElement.ownerDocument.getElementsByClassName('ng-invalid mat-form-field')[0].scrollIntoView({ behavior: 'smooth' });
});
}
到目前为止一切正常!!!
单击批准按钮后,订阅就会订阅,并且只要选择新选项卡,页面就会滚动到错误。我想取消订阅这个可观察对象,然后在再次单击“提交”按钮时重新订阅。
我试过取消订阅,但无法再次订阅。这有时会破坏订阅功能并抛出错误
我想我遗漏了什么并寻求帮助。提前致谢!!
请求的更多代码
submit()
{
if(this.bookingForm.valid){
// do some actions ....
}
else {
this.bookingForm.markAllAsTouched();
//subscribing to the event before selecting the tab
this.selectedTab.animationDone.subscribe(res => {
this.myElement.nativeElement.ownerDocument.getElementsByClassName('ng-invalid mat-form-field')[0].scrollIntoView({ behavior: 'smooth' });
});
// code to select the Tab where the error occurs .....
this.selectedTab.selectedIndex = this.errorIndex;
//unsubscribe
this.selectedTab.animationDone.unsubscribe()
} // close of else block
}// close of submit Function
取消订阅(或类似功能)是必需的,因为只有在单击“提交”按钮时才应订阅。如果未取消订阅(或暂停),则每次更改选项卡时都会调用订阅函数,并且页面会根据错误不断上下滚动。
页面浏览量
这只是为了演示。
EDIT 2 below
这里是StackBlitz Link。这只是一个示例页面,与此相比,我的页面有更多的字段和表单组。
重现问题
场景一
- 填写字段 - 名称、选项卡 1、详细信息 1
- 保持选中 tab1 并单击“提交”。
- 这应该向上滚动并显示 Tab2。按预期工作!延迟是可以接受的。
- 现在手动切换到 Tab1。
- 您可以看到页面滚动到“详细信息 2”字段。
- 每当切换选项卡时都会发生此滚动。如何停止此操作?
- 我可以通过取消注释 app.component.ts 文件中的第 38 行来实现这一点。 - 取消订阅命令。
- 在此,当我多次点击提交按钮时出现错误。
- 当我第二次点击时,订阅不起作用。
抱歉回复晚了。我有点忙。
我没有研究您尝试的 animation
部分,而是专注于基础知识,因为我们只需要关注元素,如果它是 invalid
。
submit() {
if(this.testForm.valid) {
//Code to Submit
} else {
((document.getElementsByClassName('mat-input-element ng-invalid')[0]) as HTMLElement).focus();
}
}
I came across this very cool way to do this.
import { MatInput } from '@angular/material';
import { QueryList, ViewChildren } from '@angular/core';
@ViewChildren(MatInput) inputs: QueryList <MatInput>;
submit() {
if(this.testForm.valid) {
//Code to Submit
} else {
this.inputs.find(input => !input.ngControl.valid).focus();
}
}
此外,如果您总是希望 Tab 1
在 invalid
时先被选中,则将其他条件放在 else/ else if
部分 -
if(this.testForm.get('tab1').errors) {
this.tabControl.selectedIndex = 0;
} else if(this.testForm.get('tab2').errors) {
this.tabControl.selectedIndex = 1;
}
还有一件事,在关注 invalid
元素之前,您必须稍微延迟一下,因为在 DOM 中为 Tab 2
创建 input
元素需要纳秒的时间如果 Tab 1
或 2
中的任何一个是 invalid
.
,它会关注 Details 1
delay(ms: number) {
return new Promise( resolve => setTimeout(resolve, ms) );
}
只需在 focus()
之前和 switching tabs check
之后调用
await this.delay(1);
如果您不想设置 delay
,只需在 animationDone
事件上再次设置 focus()
并将 animationDuration
时间设置为最短,这样您就不会实时查看 Details 1
上的 focus
。
点击 Methods
链接获取完整流程,如果您遇到任何问题,请告诉我。
背景
我使用的 Reactive Forms 扩展了两个选项卡(页面的前半部分只有选项卡),然后是底部带有提交按钮的长页面。我在单击“提交”按钮时进行验证。
单击“提交”按钮后,如果验证失败,页面需要滚动到错误表单字段。
我还可以根据 FormGroups 中的错误加载选项卡。
问题
- 滚动发生在选项卡加载之前。
- 为了解决第 1 点,我订阅了 animationDone 事件,然后滚动到其中的点。
submit(){
//code to select the desired tab
this.selectedTab.animationDone.subscribe(res => {
this.myElement.nativeElement.ownerDocument.getElementsByClassName('ng-invalid mat-form-field')[0].scrollIntoView({ behavior: 'smooth' });
});
}
到目前为止一切正常!!!
单击批准按钮后,订阅就会订阅,并且只要选择新选项卡,页面就会滚动到错误。我想取消订阅这个可观察对象,然后在再次单击“提交”按钮时重新订阅。
我试过取消订阅,但无法再次订阅。这有时会破坏订阅功能并抛出错误
我想我遗漏了什么并寻求帮助。提前致谢!!
请求的更多代码
submit()
{
if(this.bookingForm.valid){
// do some actions ....
}
else {
this.bookingForm.markAllAsTouched();
//subscribing to the event before selecting the tab
this.selectedTab.animationDone.subscribe(res => {
this.myElement.nativeElement.ownerDocument.getElementsByClassName('ng-invalid mat-form-field')[0].scrollIntoView({ behavior: 'smooth' });
});
// code to select the Tab where the error occurs .....
this.selectedTab.selectedIndex = this.errorIndex;
//unsubscribe
this.selectedTab.animationDone.unsubscribe()
} // close of else block
}// close of submit Function
取消订阅(或类似功能)是必需的,因为只有在单击“提交”按钮时才应订阅。如果未取消订阅(或暂停),则每次更改选项卡时都会调用订阅函数,并且页面会根据错误不断上下滚动。
页面浏览量
这只是为了演示。
EDIT 2 below
这里是StackBlitz Link。这只是一个示例页面,与此相比,我的页面有更多的字段和表单组。
重现问题
场景一
- 填写字段 - 名称、选项卡 1、详细信息 1
- 保持选中 tab1 并单击“提交”。
- 这应该向上滚动并显示 Tab2。按预期工作!延迟是可以接受的。
- 现在手动切换到 Tab1。
- 您可以看到页面滚动到“详细信息 2”字段。
- 每当切换选项卡时都会发生此滚动。如何停止此操作?
- 我可以通过取消注释 app.component.ts 文件中的第 38 行来实现这一点。 - 取消订阅命令。
- 在此,当我多次点击提交按钮时出现错误。
- 当我第二次点击时,订阅不起作用。
抱歉回复晚了。我有点忙。
我没有研究您尝试的 animation
部分,而是专注于基础知识,因为我们只需要关注元素,如果它是 invalid
。
submit() {
if(this.testForm.valid) {
//Code to Submit
} else {
((document.getElementsByClassName('mat-input-element ng-invalid')[0]) as HTMLElement).focus();
}
}
I came across this very cool way to do this.
import { MatInput } from '@angular/material';
import { QueryList, ViewChildren } from '@angular/core';
@ViewChildren(MatInput) inputs: QueryList <MatInput>;
submit() {
if(this.testForm.valid) {
//Code to Submit
} else {
this.inputs.find(input => !input.ngControl.valid).focus();
}
}
此外,如果您总是希望 Tab 1
在 invalid
时先被选中,则将其他条件放在 else/ else if
部分 -
if(this.testForm.get('tab1').errors) {
this.tabControl.selectedIndex = 0;
} else if(this.testForm.get('tab2').errors) {
this.tabControl.selectedIndex = 1;
}
还有一件事,在关注 invalid
元素之前,您必须稍微延迟一下,因为在 DOM 中为 Tab 2
创建 input
元素需要纳秒的时间如果 Tab 1
或 2
中的任何一个是 invalid
.
Details 1
delay(ms: number) {
return new Promise( resolve => setTimeout(resolve, ms) );
}
只需在 focus()
之前和 switching tabs check
await this.delay(1);
如果您不想设置 delay
,只需在 animationDone
事件上再次设置 focus()
并将 animationDuration
时间设置为最短,这样您就不会实时查看 Details 1
上的 focus
。
点击 Methods
链接获取完整流程,如果您遇到任何问题,请告诉我。