7

Imagine I have a small form and use reactive approach For example, I have two inputs

...
<input formControlName="name" name="name" type="text" class="form-control">
<input formControlName="amount" name="amount" type="text" class="form-control">
...

I want to track changes and add bootstrap classes 'is-valid'/ 'is-invalid' for appropriate cases. The problem is that the only way I see I can do it is this:

<input formControlName="name" name="name" type="text" class="form-control"
                 [ngClass]="name.invalid && name.touched ? 'is-invalid' : ''">

In ts file:

ngOnInit() {
    ...
    this.name = this.shoppingListForm.get('name');
  }

Is there a better approach. What is really annoying for me is a lot of "mud" in html.

So, if form should has default style, it means the page was loaded and input wasn't touched

I found out that I can do this, but still guess there is a better approach. By "better" I mean that won't make html so dirty

<input formControlName="name" name="name" type="text" class="form-control"
[ngClass]="{'is-invalid': name.invalid && name.touched, 
            'is-valid': name.valid, '': name.untouched}"

Any help is appreciated)

As @Muhammed stated below, the best way to do what I need is to do it through css

Just small contribution of mine in case of bootstrap 4.

The problem is that it adds border shadow, so the complete solution for me is this: for invalid input

input.ng-invalid.ng-touched{ 
    border-color: rgba(255,10,29,1) !important; box-shadow: none !important; 
} 

if it is focused, then make border look good

input.ng-invalid.ng-touched:focus{ 
    box-shadow: 0 0 0 0.2rem rgba(255,10,29,0.25) !important; 
}

3 Answers 3

12

You don't need to add the any class related to form control state change angular do this by default you just need to add a style related to these classes

input.ng-invalid.ng-touched {
    border: 1px solid red;
 }

this class indicate the input control is invalid and toched , this mean you just need to work on the style.

Sign up to request clarification or add additional context in comments.

2 Comments

As @Muhammed stated above, the best way to do what I need is to do it through css Just small contribution of mine in case of bootstrap 4. The problem is that it adds border shadow, so the complete solution for me is this: for invalid input input.ng-invalid.ng-touched{ border-color: rgba(255,10,29,1) !important; box-shadow: none !important; } if it is focused, then make border look good input.ng-invalid.ng-touched:focus{ box-shadow: 0 0 0 0.2rem rgba(255,10,29,0.25) !important; }
And what about if I want to use bootstrap styles? I tried to write .is-invalid and .is-valid inside SCSS with including bootstrap/forms and bootstrap/mixins, but my compilator started complaining about much memory consumed...
5

It is very simple!

You just have to set [ngClass] correctly in the template and name the field form with # and ngModel value (ex. #myfieldname="ngModel"). If you use Bootstrap, you can use the is-valid and is-invalid classes, like this:

<input formControlName="name" name="name" type="text" class="form-control"
    #myfieldname="ngModel"
    [ngClass]="{'is-valid': myfieldname.touched && myfieldname.valid, 'is-invalid': myfieldname.touched && myfieldname.invalid}">

2 Comments

This should be marked as the best answer. Actually, it is the only good answer here.
I mean, this is what OP is trying to avoid. The issue is you have to add such a long [ngClass] to all your inputs, just to make bootstrap detect your invalid inputs.
-1

You can have a common method in component:

isValid(field: string) {
    return (!this._form.get(field).valid && this._form.get(field).touched) ? 'is-invalid' : this._form.get(field).touched ? 'is-valid' : '';
}

Then in your element refence

[class]="isValid('title')"

1 Comment

Calling functions in templates causes issues with change detection and should be avoided - medium.com/showpad-engineering/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.