Ionic-framework: @Ionic/Angular 4.0.0 Angular forms validation status class updates not working (ng-*** != ion-***)

Created on 7 Feb 2019  路  14Comments  路  Source: ionic-team/ionic-framework

Bug Report

Ionic version:


4.0.0

Current behavior:
Using the Angular Reactive Forms API, when markAsTouched() function is called over a FormControl, ng-touched class is applied to the ion-item element but the ion-touched class is not applied.

This problem occurs with each of the Angular Forms markAs*** functions:

  • markAsTouched
  • markAsUntouched
  • markAsDirty
  • markAsPristine
  • markAsPending

_(Didn't take the time to test the reset function, but I suspect that the result will be the same.)_

Expected behavior:
Whenever an Angular FormControl status changes ng-XXX classes applied to the DOM element are updated.
ion-XXX classes should work the same way. On every FormControl status change, ion-XXX classes should also be updated.

Steps to reproduce:

  1. Change the status of a FormControl using the Angular Forms markAsXXX functions.
  2. Inspect the DOM and check the ng-XXX and ion-XXX classes applied to the corresponding ion-item.
  3. ng-XXX classes are applied, ion-XXX classes don't

Related code:


Other information:

Ionic info:

Ionic:

   ionic (Ionic CLI)             : 4.10.2 (D:\Users\****\AppData\Roaming\npm\node_modules\ionic)
   Ionic Framework               : @ionic/angular 4.0.0
   @angular-devkit/build-angular : 0.10.7
   @angular-devkit/schematics    : 7.2.3
   @angular/cli                  : 7.2.3
   @ionic/angular-toolkit        : not installed
investigation angular

Most helpful comment

This problem also occurs for the setErrors() function.
ng-valid/ng-invalid is set correspondingly, but the corresponding ionic ion-valid/ion-invalid class is not changing.

All 14 comments

This problem also occurs for the setErrors() function.
ng-valid/ng-invalid is set correspondingly, but the corresponding ionic ion-valid/ion-invalid class is not changing.

Seeing related issue in my project also. ng-touched class is added to ion-input when the control loses focus. That is expected. However, ion-touched is added to ion-item when ion-input receives focus.

Ionic team, please refer to Angular documentation. https://angular.io/api/forms/AbstractControl#touched

Hey,

I also ran into this issue using stencil, and a custom value accessor inspired by the one using by Ionic.

Because the onBlur / onChange method is not trigged by the setErrors() method, the classes are not updated => The ng-valid class is added, but the setIonClasses() is not triggered in the value accessor.

I'm trying to find a workaround, by trigerring a blur on the input, I'll let you know if I find any solution to this problem

Hey, I'm working with @gagaXD and here is our workaround for this.

First we created a Directive to add the nativeElement to the control:

native-element-injector.directive.ts

import { Directive, OnInit, ElementRef } from '@angular/core';
import { NgControl, AbstractControl } from '@angular/forms';

export interface BetterAbstractControl extends AbstractControl {
  nativeElement?: HTMLElement;
}

@Directive({
  // tslint:disable-next-line:directive-selector
  selector: '[formControlName]',
})
export class NativeElementInjectorDirective implements OnInit {
  constructor(private el: ElementRef, private control: NgControl) {}

  public ngOnInit() {
    (this.control.control as BetterAbstractControl).nativeElement = this.el.nativeElement as HTMLElement;
  }
}

In our forms, when we want to reset or setErrors:

  control.setErrors(null); // or control.setErrors(data);
  // blur nativeElement to force change it's State
  // @see https://github.com/ionic-team/ionic/issues/17414
  const betterControl: BetterAbstractControl = control;
  if (betterControl.nativeElement && control.touched) {
    betterControl.nativeElement.blur();
  }

In our input stencil component, we implement a blur method:

  /**
   * Method to blur manually.
   */
  @Method()
  blur() {
    if (this.nativeInput) {
      this.nativeInput.blur();
    }
  }

With this workaround we can Blur programmatically when we change programmatically the input state (with setErrors).

Great workaround! @Nightbr and @gagaXD Nonetheless, in my opinion, it's Ionic team's responsibility to provide its developer community with a properly working component library. I think I am going to wait for them to release a bug fix.

It is not trivial since they use ValueAccessor to bind with Angular framework and ValueAccessor has no hook when the state valid/invalid of the formControl is changed without changing the Value. We look but if Angular doesn't implement a Hook for this use case in the custom ValueAccessor https://angular.io/api/forms/ControlValueAccessor it will be very difficult.

Other try for us but with a drawback in performance is to listen with the MutationObserver class changes and refresh the ion-* classes. But it's not a valid solution because of the low performance of this (and potential loops...).

See:

Hey, just to inform that we have renamed the blur()method to setBlur() to remove the warning that stenciljs can throw.

If the Ionic controls could add the markAs* methods and then just pass it on to the Angular controls, that would work for me. Even if that was just a stop-gap until such time when the needed Angular hooks are added...

If it will be useful to someone, I will share my workaround. I update the value of the field with its own value using the submit() method.

public submit(): void {
      if (this.form.get('confirmPassword').value !== this.form.get('password').value) {
            this.form.get('confirmPassword').setErrors({ passNotEqual: true });
            this.form.get('confirmPassword').setValue(this.form.get('confirmPassword').value);
       }
}

Input 'confirmPassword' validator:

private confirmPassword(): ValidatorFn {
    return (currentControl: AbstractControl): { [key: string]: any } => {
      if ( currentControl.parent && (currentControl.value !== currentControl.parent.get('password').value) ) {
        return { passNotEqual: true };
      } else return null;
    };
  }

How can it be that after 1 year there is no response from Ionic-Team ??
This is a major issue, form validation is completely not in sync with angular and the framework is useless ?
When you have a (reactive) angular form and the user presses Submit, not errors are shown, validation is not working.
Don't you think form validation is a key concept in nearly every App ??
I really don't get, there is not even a usefull documentation on forms on the Ionic Homepage.
I don't understand how you guys can continue working on new versions without providing a framework that has the basic functionality in it...

So sad. I upgrade to version 5. Same problem.

Hi everyone,

Can you try the following dev build and let me know if it resolves the issue?

npm i @ionic/[email protected]

The proper solution to this issue is https://github.com/angular/angular/issues/10887, but we are waiting on the Angular team to implement that. In the mean time, this dev build patches the markAs* methods to manually sync Angular's form classes with Ionic's form classes.

Thanks for the issue. This has been resolved via https://github.com/ionic-team/ionic/pull/21429, and a fix will be available in an upcoming release of Ionic Framework.

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Sturgelose picture Sturgelose  路  83Comments

pavimus picture pavimus  路  90Comments

infinnie picture infinnie  路  76Comments

jgw96 picture jgw96  路  98Comments

aces-tm picture aces-tm  路  83Comments