Override ion-valid for formgroup in reactive validation

Folks, I’ve been trying to create a reactive validation for my register form in angular. Since I want either at least one or both fields filled for contact information(e-mail and cellphone number), I grouped those controls within my formbuilder, as follows below:

form: FormGroup;
  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      contact: this.fb.group({
        email: ['', {
          updateOn: 'blur',
          validators: Validators.email
        celphoneNumber: ['']
      }, { validators: this.atLeastOneValidator }),
      name: ['', Validators.required],
      password: ['', Validators.required],
      cpassword: ['', Validators.required],
      whatsapp: [false],
      birthday: [''],
      promo: [false],
      terms: [false, Validators.requiredTrue],

My custom validation function also follows:

public atLeastOneValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {
    const controls = control.controls;
    if (controls) {
      const theOne = Object.keys(controls).findIndex(key => controls[key].value !== null && controls[key].value !== '');
      if (theOne === -1) {
        return {
          atLeastOneRequired: {
            text: 'At least one should be selected'
      } else {
        return null;

Unfortunatelly, although my validation works, Ionic can’t provide ion-item parent with class ion-invalid while children input remains invalid (ion-item has both classes ion-valid and ng-invalid, but ion-valid color-highlight seem to applies).

I’ve already tried to bind ion-invalid class to form errors but Ionic ignores it for this specific class (ion-invalid is overriden by ion-valid, other classes apply though).

Is it an error that should be fixed by Ionic team or am I missing anything?

1 Like

I can confirm that this is still an issue in Ionic v6. Given the setup above, I would expect markup like this to appropriately include a formatted error:

<ion-item-group [formGroup]="form.contact">
        <ion-label position="stacked">Email</ion-label>
        <ion-input [formControl]="form.contact.email" inputmode="email"></ion-input>
        <ion-note slot="error">Invalid email</ion-note>
        <ion-label position="stacked">Phone</ion-label>
        <ion-input [formControl]="form.contact.phone" inputmode="tel"></ion-input>
    <ion-note slot="error">Email or phone required</ion-note>

This doesn’t work right now, which makes it difficult to work with cross-control validators in Angular. If anyone sees this and thinks I should write a bug report or a feature request, please let me know!