5
votes

I have created a custom autocomplete form control, that implements ControlValueAccessor and Validator and integrated it successfully into a reactive form. The input element inside the custom form control uses ngModel.

The value of the form component is valid, if the object returned by it contains a numeric ID.

For example { id: 1, name: 'Test' } would be a valid object.

Everything is working fine, but unfortunately the input element has the ng-valid CSS class applied to it, since it is not part of the reactive validation process (it uses ngModel).

The input element has my own appInput directive applied to it, so I have access to all form related classes like NgControl, or FormGroupDirective.

This is my custom autocomplete template:

<input
    #searchTerm
    appInput
    type="search"
    [ngModel]="name"
    (ngModelChange)="keyupSubject.next($event)"
/>

and it is inside a reactive formGroup:

<div [formGroup]="parentFormGroup">
    <div class="col-sm-11">

        <app-autocomplete
            formControlName="name">
        </app-autocomplete>

    </div>
</div>

I have tried ngControl and setErrors inside my appInput directive, but the CSS class is still not set.

@Input()
set errors(errors) {
    const control = this._ngControl;
    control.control.setErrors(errors);
}

How do I set the input element inside my custom form control invalid? I am asking specifically about the CSS class ng-invalid on the input element.

2
If you are willing to create your own validation service/component that uses your custom CSS classes, then you should read the following : coryrylan.com/blog/… I had a similar problem bypassed it following the above method. Maybe this is an overkill for one control only but it's a great approach if you have many types of validations.ktsangop
I already use a similar approach, but this is not what the question is about. I need to set ng-invalid on an input element.Alexander Ciesielski
OK sorry, my bad. Please try to pass the formControlName AND the id properties to your custom component like this : [formControlName]="name" [id]="controlid". Edit : id probably not needed... trying to remember how i did it a few months back, sorry...!ktsangop

2 Answers

1
votes

In your control get the NgControl

ngOnInit(): void {
    this.ngControl = this.inj.get(NgControl);
}

Then in your view you can bind any elements to the validity on ngControl:

<input [ngClass]="ngControl?.valid ? 'ng-valid' : 'ng-invalid'" class="form-control" />
0
votes

Try this approch, add #searchTerm="ngModel" to the input and test on its validation with : searchTerm.invalid

<input
    #searchTerm="ngModel"
    appInput
    type="search"
    [ngModel]="name"
    (ngModelChange)="keyupSubject.next($event)"
/>
<div *ngIf="searchTerm.invalid" class="invalid-field">
   Field Invalid
</div>