当谈到Angular 2验证时,我看到了不同的方法。基本是使用HTML5和模板/模型绑定或具有指定验证器的表单。
然而,当涉及特殊规则时,它需要大量编码和模板绑定(因此没有形式),这主要导致验证通过HTML和TS代码分散。
验证的另一个烦人的事情是你需要改变TS中的验证规则,并添加额外的HTML代码以在页面上呈现这些值(虽然这可以通过指令自动化)...
无论如何,理想的解决方案是使用规则对属性进行建模,然后向控件生成错误消息。与.NET流畅验证和ModelState类似,或者在JS世界中类似于Aurelia.io验证:http://aurelia.io/docs/plugins/validation/
答案 0 :(得分:0)
我们首先需要将FormControls链接到输入元素。它不是开箱即用的。到目前为止唯一的解决方案(至少对于纯ngModel绑定)是我发布的here。
下面的代码不适用于纯ngModel绑定,所以我做了很多实验。最新的,也由Maximillian Schwarzmuller确认应该是:
@Directive({
selector: '[ngModel]', // or 'input, select, textarea' - but then your controls won't be handled and also checking for undefined would be necessary
})
export class NativeElementInjectorDirective {
constructor(private el: ElementRef, private control : NgControl) {
(<any>control.control).nativeElement = el.nativeElement;
}
}
因此,如果在主模块中提供并导出此指令,它会将自定义nativeElement属性附加到所有FormControl 。
答案 1 :(得分:0)
接下来的事情是知道如何正确构建嵌套表单 - 请参阅link here!
此外,不仅仅是转发 ngForm ,还要转发 ngModelGroup :
@Component({
selector: 'TestAddress',
templateUrl: './address.location.html',
viewProviders: [
{ provide: ControlContainer, useExisting: NgForm },
{ provide: ControlContainer, useExisting: forwardRef(() => NgModelGroup) },
],
providers: [ MakeProvider(TestAddress) ]
})
export class TestProspectAddressLocation extends AbstractValueAccessor<any> {
...
}
我们必须使用 AbstractValueAccessor ,因此也使用MakeProvider。 Here's the link!
最后一篇:一种访问这些FormControls的方法:
this.form.get('HomeAddress.City').nativeElement
现在您可以订阅formValueChange和用户第三方进行验证,通过路径表达式访问任何控件,使用control.setErrors([])或只是通过jQuery aft附加HTML。输入强>
答案 2 :(得分:0)
仍在寻找:
答案 3 :(得分:0)
因此可以执行上面列表中的#2。
我们确实使用ngModel选择器来获取引用。对于所有输入,我们当然都有一个主控件(其中包含与验证相关的消息/代码),因此我们忽略不在该容器内的控件。
现在就来了窍门::我们确实获得了对输入本身的viewContainerRef。这使我们可以在输入后立即插入控件。由于注入是针对给定的viewContainer的,因此当隐藏输入get时,注入的控件将被破坏...
代码:
import {Directive, OnInit, Optional, ViewContainerRef} from "@angular/core";
import {NgControl} from "@angular/forms";
import {ValidationContainerDirective} from "./validation-container-directive";
/*
This directive should match all inputs (ngModel)...
If it's inside a validation container, it'll process it...
*/
@Directive({
selector: '[ngModel]'
})
export class ValidationControlForInjectorDirective implements OnInit {
private initialized: boolean = false;
constructor(@Optional() private validationContainer: ValidationContainerDirective,
private control: NgControl,
private viewContainerRef: ViewContainerRef,
) {
// skip if not inside a validation container...
if (!this.validationContainer)
return;
// mark as initialized
this.initialized = true;
}
ngOnInit(): void {
// skip if not initialized
if (!this.initialized)
return;
var thisLocator = this.control.path.join(".");
// check inputs...
if (!thisLocator)
throw new Error('Validation wire issues!');
// add a control aft. the input...but disable it temporarily...
this.validationContainer.injectComponent(this.viewContainerRef, thisLocator);
}
}
上面的injectComponent方法只是设置了我的控件并将其附加到viewContainerRef:
injectComponent(componentVcRef: ViewContainerRef, locator: string) {
// create component
var componentRef = componentVcRef.createComponent(this.componentFactoryForValidationControlFor);
// basic set up (switching server/client messages on/off is done by the doCheckManagedComponents() fnc.
(<ValidationControlFor>componentRef.instance).locator = locator;
(<ValidationControlFor>componentRef.instance).isDynamic = true;
(<ValidationControlFor>componentRef.instance).serverMessages = false;
(<ValidationControlFor>componentRef.instance).clientMessages = false;
(<ValidationControlFor>componentRef.instance).clientMessagesAlwaysVisible = this.clientMessagesAlwaysVisible;
componentRef.changeDetectorRef.detectChanges();
// NOTE:
// registering of managed component is done via the component's ngOnInit function...
// ...it was moved there, because we need to keep track also of manually added validation-message-controls!
}
答案 4 :(得分:0)
您可以尝试一个名为 ts.validator.fluent 的框架/库。通用对象验证。流利的规则。
https://github.com/VeritasSoftware/ts.validator
还有一个 Angular 6 CLI应用来演示该框架:
https://github.com/VeritasSoftware/ts-validator-app-angular6
该应用程序使用面向服务的方法来进行客户端表单验证,具有以下优点:
NPM软件包:
https://www.npmjs.com/package/ts.validator.fluent
以下是使用框架验证TypeScript模型的示例:
/* Install npm package ts.validator.fluent and then import like below */
import { IValidator, Validator, ValidationResult } from 'ts.validator.fluent/dist';
/*TypeScript model*/
class Person {
Name: string;
}
/* Validation rules */
var validatePersonRules = (validator: IValidator<Person>) : ValidationResult => {
return validator
.NotEmpty(m => m.Name, "Name cannot be empty")
.ToResult();
};
/* Populate model */
var person = new Person();
person.Name = "Shane";
/* Validate model */
/* Sync */
var validationResult = new Validator(person).Validate(validatePersonRules);
/* Async */
var validationResult = await new Validator(person).ValidateAsync(validatePersonRules);