Ionic-framework: input ng-touched not reflected properly for list-item

Created on 9 Oct 2017  路  16Comments  路  Source: ionic-team/ionic-framework

Ionic version:
[ ] 2.x
[x] 3.x
[ ] 4.x

I'm submitting a ...
[x] bug report
[ ] feature request

Current behavior:
When I have an input in a list item in a form, the angular form validation classes for the list item and the input are different. E. g., clicking into an empty required input and not entering anything sets ng-touched for the input but not the list-item. Clicking into it again updates it for the list-item as well. This behavior is different in [email protected] and [email protected].

In 3.5.2 the field stays untouched/pristine until something is entered, so it only becomes touched/dirty and invalid, if you enter something and delete it again (and leave the field).

In 3.7.1 after entering and leaving the field (without typing anything), the input becomes touched but the list-item stays untouched (the form is touched as well though). Clicking in and out again finally makes the list-item untouched as well. (it gets highlighted as invalid though, also see #13077).

Expected behavior:
The input and the list-item should reflect the same state.

Related code:
Example for 3.5.2: https://stackblitz.com/edit/ionic-qcwjxc?file=pages%2Fhome%2Fhome.html
Example for 3.7.1: https://stackblitz.com/edit/ionic-oodhy7?file=pages%2Fhome%2Fhome.html

Ionic info:

cli packages:

    @ionic/cli-utils  : 1.12.0
    ionic (Ionic CLI) : 3.12.0

global packages:

    cordova (Cordova CLI) : 7.0.1

local packages:

    @ionic/app-scripts : 3.0.0
    Cordova Platforms  : android 6.2.3 ios 4.4.0
    Ionic Framework    : ionic-angular 3.7.1

System:

    ios-deploy : 1.9.2
    Node       : v8.6.0
    npm        : 5.5.1
    OS         : macOS Sierra
    Xcode      : Xcode 9.0 Build version 9A235

Misc:

    backend : legacy

Most helpful comment

Hi, to workaround this, I've made this simply directive:

import {Directive, ElementRef, OnInit, Renderer2} from '@angular/core';

@Directive({
    selector: '[touched-workaround]',
    host: {
        '(ionBlur)': 'onBlur()'
    }
})
export class TouchedWorkaroundDirective implements OnInit {

    private parent;

    constructor(private element: ElementRef, private renderer: Renderer2) {}

    ngOnInit() {
        this.parent = this.element.nativeElement.parentElement.parentElement.parentElement;
    }

    onBlur() {
        this.renderer.addClass(this.parent, 'ng-touched');
        this.renderer.removeClass(this.parent, 'ng-untouched');
    }

}

And, then, in my form fields:

<ion-item>
    <ion-input placeholder="Email" type="email" formControlName="email" touched-workaround></ion-input>
</ion-item>

I know this is not the cleanest way, but it works for me.

All 16 comments

Hello! Thank you for opening an issue with us!

The difference as to _when_ ng-touched is applied to the input is expected. That was done as part of 3.7.0 and fixes #12102. This change makes us consistent to how Angular applies ng-touch.

The issue of it not being applied to the ion-item at the same time as the ion-input is something we will have to look into.

Thank you for using Ionic

After further testing, 3.5.2 also exhibits the bug of ng-touched not being exhibited at the ion-item at first (ion-input changes on first key press in 3.5.2, but ion-item not until second).

So the behavior is consistently wrong at least, just not as obvious in 3.5.2 because it does not have the ng-touched fix that sets ng-touched properly on the input.

Any update on this issue (specifically, the item vs. input ng-touched mismatch)? This bug has persisted for several months now and makes creating validation styling at the ion-item level impossible without writing workaround code. I have many unhappy forms in my app.

It is highly unlikely that you will see any movement on this issue until v4 is released after which it may or may not still be an issue (a lot of issues like this have been fixed as we have ported things, but not everything has necessarily been addressed with the first port).

v4 should be going into alpha soon.

Things being ported meaning your switch to Stencil components, i. e. won't be fixed in ionic-angular? What about people who don't want to pay for the switch to v4 just yet, maybe never (e. g. my boss)?

I wish there was an Ionic LTS version that would be guaranteed to be properly maintained for a certain time... from a developer perspective, issues like this are kind of frustrating :/

Thanks for the update.

I have been struggling with this problem as well! It's getting quite frustrating indeed.

Hello, Is it possible to have a workaround at least :) ? Thanks for your work !!

Hi, to workaround this, I've made this simply directive:

import {Directive, ElementRef, OnInit, Renderer2} from '@angular/core';

@Directive({
    selector: '[touched-workaround]',
    host: {
        '(ionBlur)': 'onBlur()'
    }
})
export class TouchedWorkaroundDirective implements OnInit {

    private parent;

    constructor(private element: ElementRef, private renderer: Renderer2) {}

    ngOnInit() {
        this.parent = this.element.nativeElement.parentElement.parentElement.parentElement;
    }

    onBlur() {
        this.renderer.addClass(this.parent, 'ng-touched');
        this.renderer.removeClass(this.parent, 'ng-untouched');
    }

}

And, then, in my form fields:

<ion-item>
    <ion-input placeholder="Email" type="email" formControlName="email" touched-workaround></ion-input>
</ion-item>

I know this is not the cleanest way, but it works for me.

Yeah this is very frustrating.
Ionic is supposed to be an enterprise solution but you guys seem to be jumping from project to project ignoring the basics and leaving the old ones behind.

There's been a couple issues we've encountered where the thread just ends with you saying your not going to fix it.

Please fix this important issue...I have used below as workaround
<ion-item [ngClass]="{'ng-touched ng-invalid':addProductForm.controls['control_name'].invalid}">

Hello :)

I would like to share my frustration too :'(

I have a basic form with password confirmation (so if you edit one of the two password input, they have to update their validity accordingly to each other if they have been touched)

I found out that ion-item doesn't reflect the ng-valid class accordingly to the input inside.

So when I update the input2 validity while changing input1 value, ion-item2 doesn't update to ng-valid :'(

So I'm forced to use @ZameelAmjed workaround (thanks btw) :
<ion-item [ngClass]="{'ng-valid':someForm.controls['control_name'].valid, 'ng-invalid':someForm.controls['control_name'].invalid}">

I guess it's a common usecase, so it would be really nice to have it fixed.

Loving Ionic <3

+1

+1

The below solution is working for me, using Ionic 3:

<ion-item [ngClass]="{ 'ng-touched' : form.get('myControlName').touched }">
     .......
</ion-item>

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