具有多个字段的 Angular 模板驱动表单验证

2024-04-12

假设我有一个带有一些字段的简单表单(堆栈闪电战示例 https://stackblitz.com/edit/angular-ktk7ez):

@Component({
  selector: 'my-app',
  template: 
`
<h1>AppComponent</h1>

<form>
  <h2>UserData</h2>
  <userdata [user]="model.userData"></userdata>

  <h2>Actions</h2>
  <actionbar ></actionbar>
</form>
`,
})
export class AppComponent  { ... }

@Component({
  selector: 'userdata',
  template: 
`
<span class="status {{name.status}}">{{name.status}}</span>
full name:
<input name="name" #name="ngModel" pattern="^.* .*$" required [(ngModel)]="user.name">
<br>

<h3>--- Contacts ---</h3>

<span class="status {{email.status}}">{{email.status}}</span>
email:
<input name="email" #email="ngModel" type="email" [email]="true" [(ngModel)]="user.contacts.email">
<br>


<span class="status {{phone.status}}">{{phone.status}}</span>
phone:
<input name="phone" #phone="ngModel" pattern="^[0-9]*$" [(ngModel)]="user.contacts.phone">
<br>


<h4>---- Address ----</h4>

<span class="status {{street.status}}">{{street.status}}</span>
street:
<input name="street" #street="ngModel" [(ngModel)]="user.contacts.address.street">
<br>

<span class="status {{city.status}}">{{city.status}}</span>
city:
<input name="city" #city="ngModel" [(ngModel)]="user.contacts.address.city">
<br>

<span class="status {{zipcode.status}}">{{zipcode.status}}</span>
zipcode:
<input name="zipcode" #zipcode="ngModel" pattern="^[0-9]{5}$" [(ngModel)]="user.contacts.address.zipcode">
<br>

`,
  viewProviders: [{ provide: ControlContainer, useExisting: NgForm }],
})
export class UserDataComponent  {
  @Input() user: any;
}

@Component({
  selector: 'actionbar',
  template: 
`
<span class="status {{form.status}}">{{form.status}}</span>
<input type="button" value="Submit" [disabled]="form.invalid">
`,
  viewProviders: [{ provide: ControlContainer, useExisting: NgForm }],
})
export class ActionBarComponent { ... }

(基本上是一个包含全名和联系信息字段的表单,例如电子邮件、电话、地址)

请注意,只有在有效的情况下才能提交表格。仅当嵌套在其中的所有内容都有效时,该表单才有效。

对于单个字段的验证,这很容易做到(这些字段已经有一些,如正则表达式模式和必需性)。

现在我想添加另外两个业务需求:

  1. 需要至少一项联系信息(电子邮件、电话或地址);

  2. 如果设置了地址中的任何字段,则所有字段(街道、城市、邮政编码)都是必需的。

甚至可以在模板驱动的表单中做到这一点吗?


这就是我成功实现分组验证的方式(堆栈闪电战示例 https://stackblitz.com/edit/angular-v9rjzw).

(对于我在下面粘贴的片段,括号中的省略号表示为了清晰起见,省略了这些部分;有关完整内容,请参阅上面的 stackblitz 示例)

对于每个组,我添加了一个包装元素(我认为它也可以是<ng-container>,虽然没有测试它)只是为了承受ngModelGroup指示:

<div ngModelGroup="contacts" (...) >

<h3>--- Contacts ---</h3>

email: (...input...)
phone: (...input...)

<div ngModelGroup="address" (...) >

<h4>---- Address ----</h4>

street: (...input...)
city: (...input...)
zipcode: (...input...)

</div>

</div>

现在这些新的每一个ngModelGroup可以附加验证器。由于这些验证是如此临时,我觉得它们不值得真正可重用的实现,我所需要的只是验证函数(此处仅粘贴其中一个;另一个非常简单,您可以随时参考 stackblitz ):

  ifOneThenFullAddress(c: AbstractControl): ValidationErrors | null {
    let value = c.value;

    let street = value && value.street;
    let city = value && value.city;
    let zipcode = value && value.zipcode;

    if ((street && city && zipcode) || (!street && !city && !zipcode))
      return null;

    return { ifOneThenAll: '' };
  }

(这段代码是在内部实现的UserDataComponent)

现在要使角度形式引擎调用我的函数,我必须实现一个Validator,但是一个通用的(将验证交给一个函数):

@Directive({
  selector: '[fn-validate]',
  providers: [{provide: NG_VALIDATORS, useExisting: FnValidateDirective, multi: true}]
})
export class FnValidateDirective implements Validator {
  @Input('fn-validate') fn: (c: AbstractControl) =>  ValidationErrors | null;

  validate(c: AbstractControl): ValidationErrors | null {
    return this.fn(c);
  }
}

要使用它(并绑定我的验证函数),我必须将组的元素更改为:

<div ngModelGroup="contacts" [fn-validate]="atLeastOneContact">
<div ngModelGroup="address" [fn-validate]="ifOneThenFullAddress">

瞧,整个团队得到了我的临时职能的验证。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有多个字段的 Angular 模板驱动表单验证 的相关文章

  • Angular 2将数组传递给路由器queryString

    我想传递一个数组ids 1 2 3 像这样的路由器查询字符串 http some url ids 1 ids 2 ids 3 但是当我尝试使用 const queryParams ids 1 2 3 this router navigate
  • Angular 5 Http拦截器刷新JWT令牌

    我已经实现了令牌保存 检索的逻辑 并且我也有刷新调用 问题是 当我在 HttpInterceptor 中拦截 403 时 同时进行的其他调用也会刷新令牌 我很乐意保留这些调用 直到我的令牌刷新为止 创建我所说的请求 信号量 Injectab
  • Docker 绑定安装卷不会传播由角度“ngserve”执行监视的更改事件

    请按照下列步骤操作 定义 Dockerfile FROM node alpine RUN yarn global add angular cli RUN yarn global add node sass RUN mkdir volumes
  • Angular Libraries Monorepo:是否可以为每个库使用不同的版本?

    只是一个简单的问题 我似乎找不到答案 我正在尝试构建一个应该能够使用 angular cli v8 的 monorepo 但仍然能够编译和构建为 v2 v3 v4 等制作的库 主要是组件和服务 版本之间发生了很多变化 所以让我们举个例子 V
  • 如何将窗口注入到服务中?

    我正在用 TypeScript 编写一个 Angular 2 服务 它将利用localstorage 我想注入对浏览器的引用window对象到我的服务中 因为我不想引用任何全局变量 例如 Angular 1 x window 我怎么做 这目
  • Angular 4 过滤器搜索自定义管道

    所以我试图构建一个自定义管道来在 ngFor 循环中执行多个值的搜索过滤器 我花了几个小时寻找一个好的工作示例 其中大多数都是基于以前的版本 并且似乎不起作用 所以我正在构建管道并使用控制台为我提供值 但是 我似乎无法显示输入文本 以下是我
  • 收到错误 ../node_modules/rxjs/Rx"' 没有导出成员 'of'

    我正在从教程中学习新的角度 https angular io tutorial toh pt4 inject message service https angular io tutorial toh pt4 inject message
  • 无法读取未定义的“触及”属性

    为什么我会收到此错误无法读取未定义的属性 为什么无法读取formName controls email touched但它能够阅读formName get custDetails touched
  • 升级到 firebase js sdk v8 后,在“firebase”中找不到导出“firestore”(导入为“firebase”)

    我已将 firebase JS SDK 从 v7 升级到 v8 0 0 并且像这样导入 firebase import as firebase from firebase 访问以下任何一项都会导致以下错误 firebase firestor
  • Angular 5 - 使用对象进行表单控制

    我目前正在开发一个由 Django 支持的 Angular 应用程序 该应用程序的一部分是它需要显示成员列表 成员数组看起来有点像这样 name John Smith id 3 score set name Jane Doe id 7 sc
  • 查询参数更改时,路线不会更新

    在我的应用程序中 有多个链接 其中我有一些links与相同的route但与不同的query parameters 比如说 我有这样的链接 deposits withdrawals deposits withdrawals id 1 depo
  • 如何在 Angular 4 项目中使用 ActiveXObject

    我正在尝试使用 ActiveXObject 如下所示 getActiveXObject pdfCtrl return new ActiveXObject pdfCtrl checkPDF let plugin null if this ge
  • 如何使 Angular2 Service 单例?

    我正在尝试在我的应用程序中实现身份验证防护 IE 只有经过身份验证的用户才能访问我的应用程序的某些路由 我正在遵循给出的意见here https angular io docs ts latest guide router html 用户登
  • 在 angular2 中过滤数组

    我正在研究如何在 Angular2 中过滤数据数组 我研究过使用自定义管道 但我觉得这不是我想要的 因为它似乎更适合简单的表示转换 而不是过滤大量数据 数组排列如下 getLogs Array
  • Angular 4 与 Webpack 2,动态加载脚本

    我刚刚在一个项目中尝试使用 Angular 4 和 Webpack 2 我试图在 ngOnInit 期间加载一些脚本 但遇到了一些问题 问题1 我的 ngOnInit 中有以下代码 System import node modules jq
  • 类型“typeof Control”上不存在属性“Draw”

    我正在尝试使用传单和其他传单插件实现地图组件 问题是其他插件由于某种原因无法在 TypeScript 上运行 例如 我无法使用 leaflet draw 插件编译代码并收到错误 类型 typeof Control 上不存在属性 Draw 地
  • Angular 6 StaticInjectorError(平台:核心)没有提供者

    我有一个角度版本为 4 的项目 我尝试将项目更新为 6 个角度版本 我修复了编译器在构建产品时告诉我的所有错误 他们有很多 现在项目编译没有错误 但在浏览器中无法运行 现在我被困住了 有人可以帮我解决这个问题吗 我认为这在某种程度上与延迟加
  • Typescript:按值检查对象是否存在于数组中

    我有这个数据 roles roleId 69801 role ADMIN roleId 69806 role SUPER ADMIN roleId 69805 role RB roleId 69804 role PILOTE roleId
  • 角度 2 中的动态 styleUrls?

    是否可以将样式表的 url 动态注入到组件中 就像是 styleUrls stylesheet1 css this additionalUrls 或者 一厢情愿并注意这只是假代码 export class MyComponent imple
  • 如何更改订阅值?使用 rxJS

    我正在创建一个计时器 需要你的帮助 我刚刚学习 Angular 和 rxJS 对此我有一些疑问 我正在创建一个具有启动 停止 暂停 重置功能的计时器 并且 btn Reset 必须将我的计时器 暂停 到 300 毫秒 怎么做 D 我的启动定

随机推荐

  • Python:使用 Win32 COM Api 打开 Excel 工作簿

    我使用以下代码在 Excel 中打开并显示工作簿 import win32com client as win32 excel win32 gencache EnsureDispatch Excel Application wb excel
  • Android 电视 - 现在玩纸牌图标

    我目前正在开发一个 Android 电视应用程序 但无法弄清楚如何更改当我在播放视频时离开该应用程序时出现的当前播放卡的图标 This link https developer android com training tv playbac
  • 带有对象输入数组的 Angular 2 形式

    我正在构建一个发票应用程序来学习 Angular2 我遇到的问题是如何构建行项目组件 其中一行包含 3 个输入 这些输入应来自并绑定到行项目数组中的对象 在角度1中 我可以通过添加一个轻松实现这一点ng form指向输入容器的指令 这里相当
  • 处理日期时间格式的“+00:00”

    如何将 2020 06 30 15 20 13 078196 00 00 形式的日期列转换为 pandas 中的日期时间 这就是我所做的 pd concat df df date string apply lambda s pd Serie
  • ASP.NET 如何将文件流式传输给用户

    最初 我试图找出 Response Close 和 Response End 之间的区别 但经过更多谷歌搜索和研究后 很明显我没有看到 Byte 发送回客户端的常见方式 我将在下面留下代码示例 但我想知道执行此操作的行业标准是什么 Byte
  • 通过 qbXML 设置 Employee 的 IsActive

    使用 QbXml 添加或修改员工时出现以下错误 QuickBooks 在解析提供的 XML 文本流时发现错误 我尝试过 true false 这是它返回的值 yes no 和 1 0 这些似乎都不起作用 是否可以为员工设置 IsActive
  • 我怎样才能完成反应日期

    我正在创建消息列表 显示消息发送的时间 这是我的留言集 Messages new Mongo Collection messages Messages attachSchema new SimpleSchema created type D
  • 如果字符串包含列表中的元素,则创建新的条件列[重复]

    这个问题在这里已经有答案了 我正在尝试添加一个新列keywords这将得到价值TRUE如果该单词出现在关键字列表中 该值将是FALSE如果该词没有出现在keywordslist 我的关键字由 100 多个单词组成 因此无法手动添加单词 关键
  • Mongo Java 驱动程序不遵守 limit 方法

    我有这个查询 DBCursor mongoCursor mongoCollection find query sort sort limit 5000 long mongoCursorCount mongoCursor count myLo
  • 如何创建并推送到共享或分布式数组数组?

    我编写了 Julia 代码 其中初始化一个空数组 如下所示 a 稍后在代码中 我简单地推送到该数组 如下所示 推 a b 其中 b c d e 是另一个数组 每个 b 可以具有不同的长度 这在非并行化代码中工作得很好 但是 我想在并行代码中
  • Java 垃圾收集,将引用设置为 null

    public class A A a public static void main String args A b new A new object created obj1 b a new A new object created ob
  • 使用 Werkzeug 和 Jinja2 的上下文处理器

    我的应用程序在 App Engine 上运行并使用Werkzeug http werkzeug pocoo org and Jinja2 http jinja pocoo org 2 我想要一个功能上与 Django 自己的上下文处理器等效
  • 尝试调用未定义的函数 glutInit

    我需要 python 中的一个过剩窗口 我使用 Python 3 5 和 PyOpenGL GLUT 时出现以下异常 Traceback most recent call last File D Test py line 47 in
  • Firestore没有执行操作的权限

    我正在尝试在 Firestore 中设置规则 如果每个人都经过身份验证进入应用程序 则每个人都可以读取彼此的内容 但只有文档所有者才能创建 写入 更新或删除它们 我在 Firestore 中设置了以下规则 rules version 2 s
  • Unity,如何将相机切换到第二个物体的位置?

    我在 Unity 3D 中遇到奇怪的问题 我的想法是找到数组中距离玩家最近和第二近的对象 然后我希望相机移动到最近的物体的位置并看着玩家 但如果玩家和最近的物体之间的距离太小 我希望相机移动到第二个物体的位置 我做了一些编码 但我不知道为什
  • 在 Silverlight 中使用 .NET RIA 服务有哪些陷阱?

    Silverlight可以使用WCF Web服务 基于REST的服务 NET RIA服务 但似乎Silverlight和 NET RIA服务是最受欢迎的 我想知道您在使用 NET RIA 服务实际实施 SL 时是否遇到过任何常见问题 如果继
  • 如何读取 RCFile

    我正在尝试将一个小的 RCFile 约 200 行数据 读入 HashMap 中以进行 Map Side 连接 但是在将文件中的数据变为可用状态时遇到了很多麻烦 这是我到目前为止所拥有的 其中大部分来自这个例子 http sumit1001
  • 如何从列表中选择每个第n个元素[重复]

    这个问题在这里已经有答案了 可能的重复 如何在 Haskell 中获取无限列表的每个第 N 个元素 https stackoverflow com questions 2026912 how to get every nth element
  • Java 流惰性 vs 融合 vs 短路

    我试图对 Java 流 API 中惰性求值的应用形成一个简洁而连贯的理解 目前我的理解是这样的 元素仅在需要时才被消耗 即流是惰性的 并且中间操作是惰性的 例如过滤器 仅在需要时进行过滤 中间操作可以融合在一起 如果它们是无状态的 短路操作
  • 具有多个字段的 Angular 模板驱动表单验证

    假设我有一个带有一些字段的简单表单 堆栈闪电战示例 https stackblitz com edit angular ktk7ez Component selector my app template h1 AppComponent h1