NgModel custom ValuesAccessor

An extended question about ngModel and DI.

As I see here = https://github.com/angular/angular/blob/2.0.0-beta.1/modules/angular2/src/common/forms/directives/ng_model.ts#L68 ngModel wating for providers from NG_VALUE_ACCESSOR OpaqueToken This means that if I want to create custom components that must support ngModel binding, I have to pass my ValueAccessor implementation to DI. Therefore, in my mind there are two questions.

1) How can I do this?

2) What about the default ValueAccessor for <input> elements? How to make it continue to work and use mine only for custom components?

Btw, as I see here: https://github.com/angular/angular/blob/2.0.0-beta.1/modules/angular2/src/common/forms/directives/shared.ts#L102 defaultValueAccessor last. Thus, this means that if I globally pass my System ValueAccessor throught DI than the default, it never returned.

+3
angular typescript
source share
2 answers

You can register a custom ControlValueAccessor like this in providers (the bindings attribute is deprecated) of the corresponding directive:

 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 { (...) } 

Then this accessor is automatically selected when you use ngModel and / or ngFormControl for the component with the tags selector:

 @Component({ (...) directives: [ TagsComponent, TagsValueAccessor ], template: ` <tags [(ngModel)]="company.labels" [ngFormControl]="companyForm.controls.labels"></tags> ` }) export class DetailsComponent { (...) } 

There is a complete sample in this question: Angular 2 user input form .

Hope this helps you, Thierry

+6
source share

Why create a new access attribute when you can use the internal ngModel.

This answers the second question on @Maksim Fomim

template:

 <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> 

component:

 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; } } 

Use as:

 <my-input class="col-sm-6" label="First Name" name="firstname" [(ngModel)]="user.name" required minlength="5" maxlength="20"></my-input> 
+1
source share

All Articles