angular - 根据条件订阅 Observable
问题描述
背景
我使用的反应式表单扩展了两个选项卡(仅页面的前半部分有选项卡),然后是一个底部带有提交按钮的长页面。我在单击提交按钮时进行验证。
单击提交按钮时,页面需要在验证失败时滚动到错误表单字段。
我还可以根据 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' });
});
}
到目前为止一切正常!
Once the Approve Button is clicked, the subscription subscribes, and the page scrolls to the errors whenever a new Tab is selected. 我想取消订阅这个 observable,然后在再次单击提交按钮时重新订阅。
我尝试取消订阅,但我无法再次订阅它。这有时会破坏订阅功能并引发错误
我想我错过了一些东西并寻求帮助。提前致谢 !!
根据要求提供更多代码
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
取消订阅(或类似功能)是必需的,因为它应该仅在单击提交按钮时订阅。如果它没有取消订阅(或暂停),则每次更改选项卡时都会调用订阅函数,并且页面会根据错误不断上下滚动。
页面预览
编辑 2 下面
这是StackBlitz 链接。这只是一个示例页面,与此相比,我的页面有更多的字段和表单组。
重现问题
方案 1
- 填写字段 - Name , Tab1 , Details1
- 保持 tab1 处于选中状态,然后单击提交。
- 这应该向上滚动并显示Tab2。按预期工作!延迟是可以接受的。
- 现在手动切换到 Tab1。
- 您可以看到页面滚动到 Details 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();
}
}
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;
}
还有一件事,在关注元素之前,您必须稍微延迟一下,因为在 DOMinvalid
中创建input
元素Tab 2
需要纳秒的时间,并且它关注Details 1
的是Tab 1
or中的一个2
是否为invalid
.
delay(ms: number) {
return new Promise( resolve => setTimeout(resolve, ms) );
}
focus()
只是在之前和之后调用这个switching tabs check
await this.delay(1);
如果您不想设置delay
,只需再次设置事件并将focus()
时间设置为最小,这样您就不会实时看到。animationDone
animationDuration
focus
Details 1
按照Methods
完整流程的链接,如果您遇到任何问题,请告诉我。
推荐阅读
- graphql - 使用 AWS Amplify 和 Cognito 身份验证流程将用户详细信息保存到 graphql 数据库
- tensorflow - Tensorflow 2 模型以单个输出运行,但以多个输出失败。无法挤压 dim[2],预期维度为 1,得到 3
- c# - C# 对象、列表、数据网格。需要帮助来显示它
- amazon-web-services - 测试失败时 AWS CodeBuild 不会失败
- azure - Set-AzContext:请提供有效的租户或有效的订阅
- python - 如何优化参数的权重?
- sql - SQL-查找缺失值和分组
- azure-functions - Azure 函数依赖项
- pytorch - 在 pytorch-geometric 中加载单个图像
- node.js - 在 Heroku 上部署后,我的反应节点应用程序未从后端读取数据