所以上面列表中的 #2 是可能的。
我们确实使用 ngModel 选择器来获取 ref。对于所有输入,当然我们确实有一个主控件(其中包含与验证相关的消息/代码),因此我们忽略了不在该容器内的控件。
现在诀窍来了:我们确实获得了输入本身的 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!
}