关于ngModel和DI的高级问题。
我在这里可以看到= https://github.com/angular/angular/blob/2.0.0-beta.1/modules/angular2/src/common/forms/directives/ng_model.ts#L68 ngModel供应商来自NG_VALUE_ACCESSOR OpaqueToken。这意味着如果我想创建应该支持ngModel绑定的自定义组件,我应该将我对ValueAccessor的实现传递给DI。所以我脑子里有两个问题。
1)我该怎么做?
2)<input>
元素的默认ValueAccessor是什么?如何让它继续工作并仅将我的用于自定义组件?
正如我在这里看到的那样:https://github.com/angular/angular/blob/2.0.0-beta.1/modules/angular2/src/common/forms/directives/shared.ts#L102 defaultValueAccessor是最后一个。所以这意味着如果我全局通过我的ValueAccessor通过DI系统而不是默认的从未返回。
答案 0 :(得分:6)
您可以在相应指令的ControlValueAccessor
(providers
一个已弃用)属性中注册这样的自定义bindings
:
const CUSTOM_VALUE_ACCESSOR = CONST_EXPR(new Provider(
NG_VALUE_ACCESSOR,
{useExisting: forwardRef(() => TagsValueAccessor), multi: true}));
@Directive({
selector: 'tags',
host: {'(labelsChange)': 'onChange($event)'},
providers: [CUSTOM_VALUE_ACCESSOR]
})
export class TagsValueAccessor implements ControlValueAccessor {
(...)
}
如果您对使用选择器ngModel
的组件使用ngFormControl
和/或tags
,则会自动选择此访问者:
@Component({
(...)
directives: [ TagsComponent, TagsValueAccessor ],
template: `
<tags [(ngModel)]="company.labels"
[ngFormControl]="companyForm.controls.labels"></tags>
`
})
export class DetailsComponent {
(...)
}
此问题中提供了完整的示例:Angular 2 custom form input。
希望它可以帮到你, 亨利
答案 1 :(得分:1)
为什么要在使用内部ngModel时创建新的值访问器。
将第二个问题回答给@Maksim Fomim
模板:
<div class="form-group" [ngClass]="{'has-error' : hasError}">
<div><label>{{label}}</label></div>
<input type="text" [placeholder]="placeholder" ngModel [ngClass]="{invalid: (invalid | async)}" [id]="identifier" name="{{name}}-input" />
</div>
组件:
export class MyInputComponent {
@ViewChild(NgModel) innerNgModel: NgModel;
constructor(ngModel: NgModel) {
//First set the valueAccessor of the outerNgModel
this.outerNgModel.valueAccessor = this.innerNgModel.valueAccessor;
//Set the innerNgModel to the outerNgModel
//This will copy all properties like validators, change-events etc.
this.innerNgModel = this.outerNgModel;
}
}
用作:
<my-input class="col-sm-6" label="First Name" name="firstname"
[(ngModel)]="user.name" required
minlength="5" maxlength="20"></my-input>