模型驱动形式:验证在 Angular 2 中无法按预期工作

Posted

技术标签:

【中文标题】模型驱动形式:验证在 Angular 2 中无法按预期工作【英文标题】:model driven form: validation not working as expected in Angular 2 【发布时间】:2017-03-17 04:48:28 【问题描述】:

我正在使用这样的模型驱动形式。 就像正常的验证一样,如果用户名和密码丢失,我希望我显示一条错误消息。

只要用户名和密码无效,就应该禁用提交按钮。

<div class="login">
<form #f="ngForm" (ngSubmit)="dologin(f)">
    <div class="form-group">
        <label for="username">Username</label>
        <input id="username" type="text" class="form-control" name ="username" ngModel #username="ngModel">

        <div [hidden]="username.valid" class="alert alert-danger"> Username is required.</div>
    </div>
    <div class="form-group">
        <label for="password">Password</label>
        <input id="password" type="password" class="form-control" name ="password" ngModel #password="ngModel">
        <div [hidden]="password.valid" class="alert alert-danger"> Password is required.</div>
    </div>

    <button type="submit" [disabled]="username.length<0 || password.length<0" class="btn btn-primary" type="submit">Login</button>
</form>
</div>
我看到验证 div 的行为很奇怪。有时 它显示“需要密码”,有时不是。 我想禁用提交按钮,直到表单有效为止。我试过了

[禁用]="!f.valid"

但是当我把它打印出来时 f 总是有效的 虽然我没有在用户名和密码中输入任何数据。

组件:

constructor(private router: Router,private authenticationService : AuthenticationService,private httpService:HttpService,private formBuilder:FormBuilder) 
    this.form=formBuilder.group(
        username:['',Validators.required],
        password:['',Validators.required]
    );


更新

无法绑定到“formGroup”,因为它不是“form”的已知属性。 (" ][formGroup]="form" (ngSubmit)="dologin(form.value)"> ][formControl]="form.controls['password']"> [错误->] 用户名 [错误->]

"): LoginComponent@4:8 NgControl 没有提供程序 (" 密码 [错误->];任务:Promise.then ;价值: 错误:模板解析错误:(…)错误:模板解析错误:不能 绑定到“formGroup”,因为它不是“form”的已知属性。 (" ][formGroup]="表格" (ngSubmit)="dologin(form.value)"> ][formControl]="form.controls['password']"> [错误->] 用户名 [错误->]

谢谢。

【问题讨论】:

【参考方案1】:

您设置 html 模板的方式缺少一些关键位,这些位实际上确保您已将前端连接到后端以实现反应式表单。您所拥有的似乎更符合混合了模型驱动的模板驱动形式。事实上,如果您删除 FormsModule 导入,您发布的模板甚至都不会编译。

首先删除您的 FormsModule 导入,它可以让您将两种不同的表单类型混合在一起。这将使我们走上一条需要严格的响应式表单(又名模型驱动)实现的道路。

&lt;form #f="ngForm" (ngSubmit)="dologin(f)"&gt; 将更改为&lt;form [formGroup]="form" (ngSubmit="dologin(form.value)"

您的每个输入和警告 div 都将从

<input id="username" type="text" class="form-control" name="username" ngModel #username="ngModel">

<div [hidden]="username.valid" class="alert alert-danger"> Username is required.</div>

<input id="username" type="text" class="form-control" name="username" formControlName="username">

更改是因为模型驱动表单不支持 ngModel 属性和 #[name]="ngModel",因此您将使用 formControlName 或 [formControl] 语法。

        <div [hidden]="form.controls['username'].valid || form.controls['username'].pristine"
        class="alert alert-danger"> Username is required.</div>

最后,你的提交按钮变了,注意你有两次 type="submit",来自&lt;button type="submit" [disabled]="username.length&lt;0 || password.length&lt;0" class="btn btn-primary" type="submit"&gt;Login&lt;/button&gt;

&lt;button type="submit" [disabled]="!form.valid" class="btn btn-primary"&gt;Login&lt;/button&gt;

由于我们已成功连接表单的其余部分,因此表单组上的验证现在将是正确的

这是一个你可以玩的工作 plunker:https://plnkr.co/edit/Mu9vEYGB35SwUr9TEsPI?p=preview

【讨论】:

【参考方案2】:

没有表单构建器的实现

<form #loginForm="ngForm" (ngSubmit)="login()">
    <md-input required type="email" 
        pattern="[a-z0-9!#$%&'*+/=?^_`|~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`|~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?" 
        placeholder="Email Address" #email="ngModel" name="email" 
        [(ngModel)]="loginModel.email"></md-input>
    <div *ngIf="email.dirty && !email.valid && email.touched && email.errors" class="error-message">
      <div *ngIf="email.errors.required">Email is required</div>
      <div *ngIf="!email.errors.required && email.errors.pattern">This is not a valid email</div>
    </div>
    <md-input required type="password" placeholder="Password" #password="ngModel" name="password" [(ngModel)]="loginModel.password"></md-input>
    <div *ngIf="password.dirty && !password.valid && password.touched && password.errors" class="error-message">
      <div *ngIf="password.errors.required">Password is required</div>
    </div>
    <button ma-raised-button [disabled]="!loginForm.valid">
      Login
    </button>
</form>

组件:

ngOnInit() 
    this.loginModel = email: '', password: '';


login() 
    console.log(this.loginModel['email']);
    console.log(this.loginModel['password']);

【讨论】:

以上是关于模型驱动形式:验证在 Angular 2 中无法按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2.0 中的模型驱动表单验证问题

Angular Material步进线性验证无法按预期工作

以 angular2 模型驱动形式重用组件

如何通过模板驱动形式验证 Angular 7 中的下拉列表

Angular2中的复选框组处理和验证

模板驱动形式将所有内容标记为已触摸 - Angular 7