0

I have the following code repeatedly in my forms within my components:

<div class="form-group row">
  <label class="col-sm-4 col-form-label" for="description">Description</label>
  <input class="form-control form-control-lg" 
         id="description" 
         type="text" placeholder="..." 
         formControlName="description" 
         [ngClass]="{ 
           'form-control-warning': descriptionCtrl.untouched && descriptionCtrl.invalid, 
           'form-control-success': descriptionCtrl.valid, 
           'form-control-danger': descriptionCtrl.touched && descriptionCtrl.invalid }">
</div>
... Another "blocks" with the same code

So, in order to simplify this, I've created the following method:

handleClass = (control: AbstractControl): any => {
  if (control.valid) {
    return 'form-control-success';
  } else {
    if (control.touched) {
      return 'form-control-danger';
    } else {
      return 'form-control-warning';
    }
  }
}

In template:

[ngClass]="handleClass(control)"

However this is still not what I want, since I need to do create this method on all components. I'm looking for a general way to do this dynamically.

PS: All inputs in my project have the same rule as the input above.

What's the best way to accomplish this? I hope my question was clear enough.

1

1 Answer 1

3

Write a directive to handle this, like so:

@Directive({ selector: '[formValidBorders]'})
export class FormValidBorders implements OnChanges {
    @Input('formValidBorders') formValue: AbstractControl;

    constructor(private el: ElementRef) { }

    ngOnChanges(){
        this.el.nativeElement.className = this.handleClass(formValue);
    }

    private handleClass(control: AbstractControl) {

      if (control.valid) {
        return 'form-control-success';
      } 
      else if (control.touched) {
          return 'form-control-danger';
        } 
      else {
          return 'form-control-warning';

      }
    }
}

Then on your element:

<input class="form-control form-control-lg" 
         id="description" 
         type="text" placeholder="..." 
         formControlName="description" 
         [formValidBorders]="form.get('description')">

Something like this should work, with imports of course.

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

9 Comments

Remove the return type annotation please, any is absolutely wrong here. Also, this doesn't make any sense since you are not doing anything with the result.
@AluanHaddad I accidently saved the wrong copy of the answer, the updated answer is in place.
You are using a return type of any, what are you returning? (hint the compiler knows best if you let it do its job)
Oh! Sorry, I copied that from his question. That doesn't need a return type.
Right, it is often best to let it infer the type in the other case too. It is always better than using any. So in either case you can leave off the return type which, incidentally, is void in your updated answer.
|

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.