是否有一种方法可以在提交时触发反应形式的所有验证器,而不仅仅是“脏”#34;和"触摸"事件
这样做的原因是我们有一个非常大的表格,它没有表明是否需要某个字段,并且用户可能会错过一些必需的控件,因此在提交时,预计所有的将显示最终用户遗漏的无效字段。
我尝试将表单标记为"触及"使用
FormGroup.markAsTouched(true);
它有效,所以我也尝试将其标记为"脏"
FormGroup.markAsDirty(true);
但是班级的css仍然是" ng-pristine",
有没有办法从组件手动触发它,我试着谷歌搜索无济于事,谢谢你提前!
更新
我已经通过迭代FormGroup.controls并将其标记为"脏"来完成它,但是有一个"标准"这样做的方法。
答案 0 :(得分:14)
这可以通过 here 的示例来实现,您可以在其中使用NgForm
指令:
<form [formGroup]="heroForm" #formDir="ngForm">
然后在验证邮件中检查表单是否已提交:
<small *ngIf="heroForm.hasError('required', 'formCtrlName') && formDir.submitted">
Required!
</small>
答案 1 :(得分:12)
有多种方法可以解决问题。如果你有嵌套的表单组,@ Splaktar的答案将不起作用。所以,这是适用于嵌套表单组的解决方案。
解决方案1 :遍历所有表单组和表单控件,并以编程方式触摸它们以触发验证。
模板代码:
<form [formGroup]="myForm" (ngSubmit)="onSubmit()" novalidate>
...
<button type="submit" class="btn btn-success">Save</button>
</form>
component.ts代码:
onSubmit() {
if (this.myForm.valid) {
// save data
} else {
this.validateAllFields(this.myForm);
}
}
validateAllFields(formGroup: FormGroup) {
Object.keys(formGroup.controls).forEach(field => {
const control = formGroup.get(field);
if (control instanceof FormControl) {
control.markAsTouched({ onlySelf: true });
} else if (control instanceof FormGroup) {
this.validateAllFields(control);
}
});
}
解决方案2 :使用变量检查表单是否已提交。 仅供参考:目前正在测试ngForm的提交字段,并将包含在将来的Angular版本中。因此不需要创建自己的变量。
component.ts代码
private formSubmitAttempt: boolean;
onSubmit() {
this.formSubmitAttempt = true;
if (this.myForm.valid) {
console.log('form submitted');
}
}
模板代码:
<form [formGroup]="myForm" (ngSubmit)="onSubmit()" novalidate>
<div class="form-group">
<label class="center-block">
Name:
<input class="form-control" formControlName="name">
</label>
<div class="alert alert-danger" *ngIf="myForm.get('name').hasError('required') && formSubmitAttempt">
Name is required
</div>
...
</form>
答案 2 :(得分:9)
几个月后回来,我在这里分享基于所有评论的改进版本,仅供记录:
markAsTouched(group: FormGroup | FormArray) {
group.markAsTouched({ onlySelf: true });
Object.keys(group.controls).map((field) => {
const control = group.get(field);
if (control instanceof FormControl) {
control.markAsTouched({ onlySelf: true });
} else if (control instanceof FormGroup) {
this.markAsTouched(control);
}
});
}
希望它会有用!
答案 3 :(得分:4)
这可以通过markAsTouched()
完成。在合并PR #26812之前,您可以使用
TEST_F(MDNodeTest, PrintFromMetadataAsValue)
您可以在source code中找到更多信息。
答案 4 :(得分:2)
我找到了可能感兴趣的东西:
在提交时,我设置submitAttempt = true
并将其放入应进行验证的div中:
nickname.touched || nickname.dirty || (nickname.untouched && submitAttempt)
含义: 如果没有触及,我们尝试提交,则会显示错误。
答案 5 :(得分:1)
我的应用程序有很多表单和输入,所以我创建了各种自定义表单组件(用于普通文本输入,textarea输入,选择,复选框等),这样我就不需要重复详细的HTML / CSS和表单验证UI逻辑到处都是。
我的自定义基本表单组件会查找其托管df = pd.DataFrame({'visitor_id':[1,1,2,2,1,1],'visit_id':[5,6,1,2,7,8], 'page_views':[10,20,30,30,40,50]})
df['New']=df.groupby('visitor_id').visit_id.transform('max') - df.visit_id
df['weight'] = pd.Series([1/2]*len(df)).pow(df.New.values)
df
page_views visit_id visitor_id New weight
0 10 5 1 3 0
1 20 6 1 2 0
2 30 1 2 1 0
3 30 2 2 0 1
4 40 7 1 1 0
5 50 8 1 0 1
并使用其FormGroupDirective
属性以及submitted
个州FormControl
,valid
等。)确定需要在UI上显示哪个验证状态和消息(如果有)。
此解决方案
touched
属性submitted
- 绑定ngSubmit
方法中的任何其他表单验证处理<强>形状base.component:强>
onSubmit
<强>形状text.component:强>
import {Host, Input, OnInit, SkipSelf} from '@angular/core';
import {FormControl, FormGroupDirective} from '@angular/forms';
export abstract class FormBaseComponent implements OnInit {
@Input() id: string;
@Input() label: string;
formControl: FormControl;
constructor(@Host() @SkipSelf()
private formControlHost: FormGroupDirective) {
}
ngOnInit() {
const form = this.formControlHost.form;
this.formControl = <FormControl>form.controls[this.id];
if (!this.formControl) {
throw new Error('FormControl \'' + this.id + '\' needs to be defined');
}
}
get errorMessage(): string {
// TODO return error message based on 'this.formControl.errors'
return null;
}
get showInputValid(): boolean {
return this.formControl.valid && (this.formControl.touched || this.formControlHost.submitted);
}
get showInputInvalid(): boolean {
return this.formControl.invalid && (this.formControl.touched || this.formControlHost.submitted);
}
}
<强>形状text.component.html:强>
import {Component} from '@angular/core';
import {FormBaseComponent} from '../form-base.component';
@Component({
selector: 'yourappprefix-form-text',
templateUrl: './form-text.component.html'
})
export class FormTextComponent extends FormBaseComponent {
}
<强>用法:强>
<label class="x_label" for="{{id}}">{{label}}</label>
<div class="x_input-container"
[class.x_input--valid]="showInputValid"
[class.x_input--invalid]="showInputInvalid">
<input class="x_input" id="{{id}}" type="text" [formControl]="formControl">
<span class="x_input--error-message" *ngIf="errorMessage">{{errorMessage}}</span>
</div>
答案 6 :(得分:1)
现在有了updateOn:“提交”选项,该选项将导致验证在提交时触发,例如:
this.myForm = new FormGroup({},{updateOn: ‘submit’});
答案 7 :(得分:0)
如果我能得到您的要求。您只想在每次提交时更新验证消息。最好的方法是存储控件状态的历史记录。
export interface IValdiationField {
submittedCount: number;
valid: boolean;
}
class Component {
// validation state management
validationState: Map<string, IValdiationField | number> = new Map();
constructor() {
this.validationState.set('submitCount', 0);
}
validationChecker(formControlName: string): boolean {
// get submitted count
const submittedCount: number = (this.validationState.get('submitCount') || 0) as number;
// form shouldn't show validation if form not submitted
if (submittedCount === 0) {
return true;
}
// get the validation state
const state: IValdiationField = this.validationState.get(formControlName) as IValdiationField;
// set state if undefined or state submitted count doesn't match submitted count
if (state === undefined || state.submittedCount !== submittedCount) {
this.validationState.set(formControlName, { submittedCount, valid: this.form.get(formControlName).valid } );
return this.form.get(formControlName).valid;
}
// get validation value from validation state managment
return state.valid;
}
submit() {
this.validationState.set('submitCount', (this.validationState.get('submitCount') as number) + 1);
}
}
然后在html代码* ngIf =“!validationChecker('formControlName')”中显示错误消息。
答案 8 :(得分:0)
“污秽”,“感动”,“提交”可以使用下一种方法进行组合:
<form [formGroup]="form" (ngSubmit)="doSomething()" #ngForm="ngForm">
<input type="text" placeholder="Put some text" formControlName="textField" required>
<div *ngIf="textField.invalid && (textField.dirty || textField.touched || ngForm.submitted)">
<div *ngIf="textField.errors.required">Required!</div>
</div>
<input type="submit" value="Submit" />
</form>
答案 9 :(得分:0)
与开箱即用的验证器一起使用,最好的方法是简单地检查用户点击“提交”时表单组是否有效。
markAllAsTouched()
然后可用于触发表单每个字段的有效性检查:
// Component
loginForm: FormGroup;
ngOnInit() {
this.loginForm = new FormGroup({
username: new FormControl(null, [
Validators.required,
Validators.minLength(4)
]),
password: new FormControl(null, [
Validators.required,
Validators.minLength(4)
]),
});
}
submitLoginForm() {
if (!this.loginForm.invalid) { // Checks form input validity
// Form input is valid
console.log('Valid login attempt - allow submission');
} else {
// Form input is not valid
this.loginForm.markAllAsTouched(); // Trigger validation across form
console.log('Invalid login attempt - block submission');
}
}
// Template
<form id="login_wrapper" [formGroup]="loginForm" (ngSubmit)="submitLoginForm()">
<h1>Log in</h1>
<mat-form-field color="accent">
<mat-label>Username</mat-label>
<input matInput
placeholder="Username"
type="text"
formControlName="username">
<mat-error
*ngIf="loginForm.controls.username.invalid && (loginForm.controls.username.dirty || loginForm.controls.username.touched)">
Please enter a valid username
</mat-error>
</mat-form-field>
<mat-form-field color="accent">
<mat-label>Password</mat-label>
<input matInput
placeholder="Password"
type="password"
formControlName="password">
<mat-error
*ngIf="loginForm.controls.password.invalid && (loginForm.controls.password.dirty || loginForm.controls.password.touched)">
Please enter a valid password
</mat-error>
</mat-form-field>
<button id="login_btn"
mat-flat-button
color="primary"
type="submit">Login</button>
</form>