Angular 2 - 将表单验证移至指令
Angular 2 - Move form validation to directive
我想将表单验证移至指令,并在表单中的所有字段中保留 ngForm 验证。
在以下示例中,我将以下验证 (1. Works) 的输入文本字段移至指令。但是当我将它移动到指令时,模型更新正确,但 form.valid 操作不受指令影响。
表单无效,因为输入文本没有值。当它被赋予一个值时,按钮被激活并且表单有效。
1.作品:
<form (ngSubmit)="onSubmit()" #aliasForm="ngForm">
<div class="form-group">
<label for="firstname">Fornavn</label>
<input type="text" class="form-control" id="firstname"
required
[(ngModel)]="model.primaryAlias.firstName" name="firstname"
#name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Fornavn er påkrævet
</div>
</div>
<div class="form-group col-sm-6">
<p-dropdown [style]="{'width':'150px'}" [options]="genders" [(ngModel)]="model.primaryAlias.gender" name="genders" [required]="true"></p-dropdown>
</div>
优化
2。不使用指令(p-输入):
<form (ngSubmit)="onSubmit()" #aliasForm="ngForm">
<p-input [(value)]="model.primaryAlias.firstName" directiveLabel="Fornavn"></p-input>
<div class="form-group">
<p-dropdown [style]="{'width':'150px'}" [options]="genders" [(ngModel)]="model.primaryAlias.gender" name="genders" [required]="true"></p-dropdown>
</div>
<button type="submit" class="btn btn-success pull-right" [disabled]="!aliasForm.form.valid">Opret</button></form>
p-input.ts:
p-input.html:
<div class="form-group">
<label for="firstname">Fornavn</label>
<input type="text" class="form-control" id="firstname"
required
[(ngModel)]="value" (ngModelChange)="onChange($event)" ngControl="value" name="firstname"
#name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Fornavn er påkrævet
</div>
如何将验证移至指令并保持表单处理,使整个表单完好无损?
我会为您的自定义指令实施 ControlValueAccessor
,例如:
p-input.ts
export const INPUT_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => InputTestComponent),
multi: true
};
@Component({
selector: 'p-input',
template: `
<div class="form-group">
<label for="firstname">{{directiveLabel}}</label>
<input type="text" class="form-control" id="firstname"
required
[(ngModel)]="value"
(ngModelChange)="onModelChange($event)" #name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Fornavn er påkrævet
</div>
</div>
`,
providers: [INPUT_VALUE_ACCESSOR]
})
export class InputTestComponent implements ControlValueAccessor {
onChange = (_: any) => {};
onTouched = () => {};
value: string;
@Input() directiveLabel: string;
@ViewChild('name') inputRef: ElementRef;
constructor(private renderer: Renderer2) {}
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
onModelChange(newValue: string) {
this.value = newValue;
this.onChange(this.value);
}
writeValue(val: any): void {
this.value = val;
}
setDisabledState(isDisabled: boolean): void {
this.renderer.setProperty(this.inputRef.nativeElement, 'disabled', isDisabled);
}
}
parent.html
<p-input required
name="firstName" [(ngModel)]="model.primaryAlias.firstName" directiveLabel="Fornavn">
</p-input>
或手动向您的表单添加内部输入控件:
p-input.ts
@Component({
selector: 'p-input',
template: `
<div class="form-group">
<label for="firstname">{{directiveLabel}}</label>
<input type="text" class="form-control" id="firstname"
required
[(ngModel)]="value"
(ngModelChange)="onChange($event)" name="firstname"
#name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Fornavn er påkrævet
</div>
</div>
`
})
export class InputTestComponent {
@Input() value: string;
@Input() directiveLabel: string;
@Output() valueChange: EventEmitter<string> = new EventEmitter();
@ViewChild(NgControl) inputControl: NgControl;
constructor(@Optional() private controlContainer: ControlContainer) {}
ngOnInit() {
if(this.controlContainer) {
this.controlContainer.formDirective.addControl(this.inputControl);
}
}
onChange(newValue: string) {
this.value = newValue;
this.valueChange.emit(this.value);
}
}
parent.html
<p-input [(value)]="model.primaryAlias.firstName" directiveLabel="Fornavn"></p-input>
我想将表单验证移至指令,并在表单中的所有字段中保留 ngForm 验证。 在以下示例中,我将以下验证 (1. Works) 的输入文本字段移至指令。但是当我将它移动到指令时,模型更新正确,但 form.valid 操作不受指令影响。 表单无效,因为输入文本没有值。当它被赋予一个值时,按钮被激活并且表单有效。
1.作品:
<form (ngSubmit)="onSubmit()" #aliasForm="ngForm">
<div class="form-group">
<label for="firstname">Fornavn</label>
<input type="text" class="form-control" id="firstname"
required
[(ngModel)]="model.primaryAlias.firstName" name="firstname"
#name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Fornavn er påkrævet
</div>
</div>
<div class="form-group col-sm-6">
<p-dropdown [style]="{'width':'150px'}" [options]="genders" [(ngModel)]="model.primaryAlias.gender" name="genders" [required]="true"></p-dropdown>
</div>
优化
2。不使用指令(p-输入):
<form (ngSubmit)="onSubmit()" #aliasForm="ngForm">
<p-input [(value)]="model.primaryAlias.firstName" directiveLabel="Fornavn"></p-input>
<div class="form-group">
<p-dropdown [style]="{'width':'150px'}" [options]="genders" [(ngModel)]="model.primaryAlias.gender" name="genders" [required]="true"></p-dropdown>
</div>
<button type="submit" class="btn btn-success pull-right" [disabled]="!aliasForm.form.valid">Opret</button></form>
p-input.ts:
p-input.html:
<div class="form-group">
<label for="firstname">Fornavn</label>
<input type="text" class="form-control" id="firstname"
required
[(ngModel)]="value" (ngModelChange)="onChange($event)" ngControl="value" name="firstname"
#name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Fornavn er påkrævet
</div>
如何将验证移至指令并保持表单处理,使整个表单完好无损?
我会为您的自定义指令实施 ControlValueAccessor
,例如:
p-input.ts
export const INPUT_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => InputTestComponent),
multi: true
};
@Component({
selector: 'p-input',
template: `
<div class="form-group">
<label for="firstname">{{directiveLabel}}</label>
<input type="text" class="form-control" id="firstname"
required
[(ngModel)]="value"
(ngModelChange)="onModelChange($event)" #name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Fornavn er påkrævet
</div>
</div>
`,
providers: [INPUT_VALUE_ACCESSOR]
})
export class InputTestComponent implements ControlValueAccessor {
onChange = (_: any) => {};
onTouched = () => {};
value: string;
@Input() directiveLabel: string;
@ViewChild('name') inputRef: ElementRef;
constructor(private renderer: Renderer2) {}
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
onModelChange(newValue: string) {
this.value = newValue;
this.onChange(this.value);
}
writeValue(val: any): void {
this.value = val;
}
setDisabledState(isDisabled: boolean): void {
this.renderer.setProperty(this.inputRef.nativeElement, 'disabled', isDisabled);
}
}
parent.html
<p-input required
name="firstName" [(ngModel)]="model.primaryAlias.firstName" directiveLabel="Fornavn">
</p-input>
或手动向您的表单添加内部输入控件:
p-input.ts
@Component({
selector: 'p-input',
template: `
<div class="form-group">
<label for="firstname">{{directiveLabel}}</label>
<input type="text" class="form-control" id="firstname"
required
[(ngModel)]="value"
(ngModelChange)="onChange($event)" name="firstname"
#name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Fornavn er påkrævet
</div>
</div>
`
})
export class InputTestComponent {
@Input() value: string;
@Input() directiveLabel: string;
@Output() valueChange: EventEmitter<string> = new EventEmitter();
@ViewChild(NgControl) inputControl: NgControl;
constructor(@Optional() private controlContainer: ControlContainer) {}
ngOnInit() {
if(this.controlContainer) {
this.controlContainer.formDirective.addControl(this.inputControl);
}
}
onChange(newValue: string) {
this.value = newValue;
this.valueChange.emit(this.value);
}
}
parent.html
<p-input [(value)]="model.primaryAlias.firstName" directiveLabel="Fornavn"></p-input>