#Technical Issue with Reusable Input Component and Angular Validators

10 messages · Page 1 of 1 (latest)

compact condor
#

Context:
I'm working on a reusable input component that I wanna to integrates with Angular validators and handles all validators based on the formControl state. However, I'm encountering a issue/bug where the state appears to be incorrect (something like state - 1). Interestingly, adding a setTimeout to delay the operation temporarily resolves the issue, Also I tried to pass the formControl as an Input also I tried signal inputs all of them has the same behavior.
Steps Taken:
Create a reusable input component (InputComponent) that only has the input
Create the parent component (HomeComponent) to use the input.
Implement two interfaces in the InputComponent (ControlValueAccessor, Validator).
the implementation of validate(control: AbstractControl): ValidationErrors function should contain the state of the parent form
Input data:
any text in the input

expected result in the validate(control: AbstractControl): ValidationErrors function:
control.errors => min-length

Actual Behavior:
control.errors => required: true

weird stuff:
in the console if I open the control object I will find the errors inside in the correct state

royal gust
#

You didn't post code, so it's quite hard to figure out what you're doing.
But what makes you think that the validate method should see the minlength and not the required error? Is there some specification somewhere guaranteeing that the validators run and change the state of the control before the validate method is called?
And most importantly: why do you care? The validate method should return ValidationErrors or null, and shouldn't care about any other error that could be detected by other validators.

compact condor
#

HomeComponent.HTML

      <fsx-input
        formControlName="customInput"
        placeholder="Enter text"
      ></fsx-input>
      <button type="submit">Submit</button>
    </form>```
#

InputComponent.HTML

  [value]="value"
  (input)="handleInput($event)"
  [placeholder]="placeholder"
  [disabled]="disabled"
  class="custom-input"
/>
<div *ngIf="" class="error">This field idassads required</div>```
#

InputComponent.ts

@Component({
  selector: 'fsx-input',
  standalone: true,
  templateUrl: './input.component.html',
  styleUrls: ['./input.component.scss'],
  imports: [ReactiveFormsModule, CommonModule],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => InputComponent),
      multi: true,
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => InputComponent),
      multi: true,
    },
  ],
})
export class InputComponent implements ControlValueAccessor, Validator {
  @Input() placeholder: string = '';
  @Input() errorMessages: { [key: string]: string } = {};

  validate(control: AbstractControl): ValidationErrors | null {
    console.log('control', control);
    console.log('control.errors before set-time', control.errors);
    setTimeout(() => {
      console.log('control.errors', control.errors);
      console.log('control.status', control.status);
      console.log('control.value', control.value);
    });

    return null;
  }
}
#

Sorry if it wasn't clear for you, I'm working on creating a reusable inputComponent in storybook,
first it should contain minLength not required because I added a text in the input so it should remove the required error,

there is nothing that changes the state of the control before the validate method

If I got the last question right, so I care because I wanna control the errors of this control form the Input component, so the validate method should get back the right ValidationErrors

royal gust
#

Post your code as a stackblitz, as explained in #how-to-get-help . But you haven't answered my question. You type something in the inputs. All the validators are run, then the control status and errors are updated. What makes you think that the minlength validator should run before your validate method? What makes you think the status and errors of the control should be updated before your validate method is called? And why do you care?

compact condor
#

I got you, and it is totally my fault to explain it, I don't care about the validate method, what I'm caring is to have the control updated state in my reusable input component(Also without pass the control as a parameter) so what I found after my research that I can control the validations of this control from this validate method from Validator Interface.

but Also when I faced this problem I tried to pass the formControl or use signal inputs to have a real-time input updates and they gave me the same result

Let me know if I made my self clear, please 🙏

royal gust
#

If you don't want to validate your control, then you shouldn't have a validate method. You will have the updated state eventually, i.e. after all the validators have been called. The state won't be updated while the validators are being called, and the validate method is a validator. See https://stackblitz.com/edit/stackblitz-starters-v99cum?file=src%2Fapp%2Finputs%2Finputs.component.html,src%2Fapp%2Finputs%2Finputs.component.ts,src%2Fmain.ts,src%2Fapp%2Finputs%2Finputs.component.spec.ts: as you can see, the errors are correctly displayed.