0

I'm trying to use ngControl to apply error classes based on user's input.

Somehow, I can't make it to work. I see that appropriate classes are set (line ng-invalid), but when trying to use name.valid (where name is my ngControl) it doesn't work.

html:

   <div ngClass="{alert: name.invalid}">
      <label for="name">Name</label>
      <input ngControl="name" #name id="name" [(ngModel)]="user.name"/>
   </div> 

</div>

js

export class App {
   userForm: any;
   user: any;

   constructor(
     private _formBuilder: FormBuilder) {

     this.user = {name: 'Ben'};
     this.userForm = this._formBuilder.group({
        'name': ['', Validators.required]
     });
   }

}

I saw on angular.io examples that they do use it like this (just for other cases, like show/hide divs)?

Here's the simple plunker: http://plnkr.co/edit/BKx4yplIOu44tk7Mfolc?p=preview

When input field is empty, I would expect that upper div gets alert class, but that doesn't happen.

Ned
  • 3,961
  • 8
  • 31
  • 49

1 Answers1

2

In fact there are three things to change in your template:

  • ngClass should be [ngClass]. Otherwise the value is considered as a string and not as an expression.
  • #name should be #name="ngForm". Otherwise you reference the DOM element and not the control.
  • there is no invalid property on controls in Angular2 but only a valid one.

Here is the refactored code:

<div [ngClass]="{alert: !name.valid}">
  <label for="name">Name</label>
  <input ngControl="name" #name="ngForm"
      required id="name" [(ngModel)]="user.name"/>
</div>

Here is the plunkr: http://plnkr.co/edit/OJfb9VDqlrRH4oHXQJyg?p=preview.

Note that you can't leverage of FormBuilder with ngControl since the latter allows you to define inline form. With FormBuilder you must use ngFormControl instead.

Here is a sample:

<div [ngClass]="{alert: !userForm.controls.name.valid}">
  <label for="name">Name</label>
  <input [ngFormControl]="userForm.controls.name"
      id="name" [(ngModel)]="user.name"/>
</div>

See this article for more details:

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • thanks a lot. I tried so many combinations, that finally I made some typos. But you made some things clear, and I see it's working now. I only have one more question. I see in console that this exception is thrown: `Uncaught (in promise): EXCEPTION: Expression '{alert: !name.valid} in App@4:7' has changed after it was checked.` I see it in my app, and that's why I started with all the changes and workarounds, and finally ended up here. Do you have an idea, how it should be fixed (in my app, it happens with combination of name.valid and name.touched). – Ned Apr 06 '16 at 15:40
  • 1
    You're welcome! I think that you could try to call the `detectChanges` method of `ChangeDetectorRef` within the `ngOnInit` method of your component. See this question: http://stackoverflow.com/questions/35520018/how-to-trigger-change-detection-in-angular2/35520764#35520764. – Thierry Templier Apr 06 '16 at 15:47