ngModel自定义ValuesAccessor

时间:2016-01-25 15:15:01

标签: typescript angular

关于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系统而不是默认的从未返回。

2 个答案:

答案 0 :(得分:6)

您可以在相应指令的ControlValueAccessorproviders一个已弃用)属性中注册这样的自定义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>