我想实现我自己的
Property
指令,其行为应类似于现有的 FormControlName
指令。
它应该使用给定 name
的 Property
来充当 formControlName
的角色。
interface Property {
name: string;
// more
}
基本上我希望这两个是等价的:
<form [formGroup]="myFormGroup">
<input type="text" [property]="myProperty" />
</form>
<form [formGroup]="myFormGroup">
<input type="text" [formControlName]="myProperty.name" />
</form>
我的方法是扩展
FormControlName
但这没有成功,因为 <input>
元素保持为空。
@Directive({
selector: '[property]',
providers: [
{
provide: NgControl,
useExisting: forwardRef(() => PropertyDirective),
}
],
})
export class PropertyDirective<TProperty extends Property<SimpleValue, string, string>> extends FormControlName {
public readonly property = input.required<TProperty>();
constructor(
@Optional() @Host() @SkipSelf() parent: ControlContainer,
@Optional() @Self() @Inject(NG_VALIDATORS) validators: (Validator | ValidatorFn)[],
@Optional()
@Self()
@Inject(NG_ASYNC_VALIDATORS)
asyncValidators: (AsyncValidator | AsyncValidatorFn)[],
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[],
) {
super(parent, validators, asyncValidators, valueAccessors, null);
effect(() => {
const property = this.property();
if (!property) {
return;
}
this.name = property.name;
});
}
}
如何创建一个与上面给出的示例模板类似的指令?
Property
指令并覆盖 ngOnChanges
钩子以无错误地初始化控件之外,因为 ngOnChanges
对于具有空 formControlName
属性的 name
将在 effect
之前工作。 示例:
override ngOnChanges(changes:SimpleChanges) {
this.name = this.property().name;
super.ngOnChanges(changes);
}
controlValueAccessor
实现 Property
,因为 defaultValueAccessor
使用 formControlName
绑定到特定选择器(示例:input:[formControlName]
)。