4

I have updated my application from Angular 2.x to Angular 4.0.0. From this time onwards, I am getting the following issue with input type text form control :


On IE11, when receives focus, a placeholder is removed and form control is set to dirty and pristine is set to false. On Chrome / FF, this issue never occurs.

On IE11 an input element becomes dirty as soon as its focused. Unlike Chrome for example where you have to type in it first.

HTML :

<input 
  type="text" 
  class="form-control" 
  id="processName" 
  [(ngModel)]="process.displayName" 
  [disabled]="isProcessLoading"
  #processName="ngModel"
  maxLength="64" 
  pattern="^.*\S.*" 
  name="processName" 
  placeholder="{{'PROCESS-FORM.name-placeholder' | translate}}"
  required 
  placeholderRequired 
  [inputBinding]="processName" 
/>

I have created one directive which will when in focus, set all errors to null (valid).

@Directive({
  selector: '[placeholderRequired]'
})
export class PlaceHolderDirective {
  @Input() inputBinding: any = null;

  constructor(private elementRef: ElementRef) {
  }

  @HostListener('focus', ['$event'])
  handleFocus(event: any) {
    if (navigator.appVersion && navigator.appVersion.indexOf('.NET') > -1) {
      // IE only
      if (!this.inputBinding._control._value) {
        this.inputBinding.control.setErrors(null);
        setTimeout(() => this.inputBinding.control.setErrors(null),0);
      }
    }
  }

  @HostListener('mousedown', ['$event'])
  handleMouseDown(event: any) {
    if (navigator.appVersion && navigator.appVersion.indexOf('.NET') > -1) {

      if (!this.inputBinding._control._value) {
        this.inputBinding.control.setErrors(null);
        setTimeout(() => this.inputBinding.control.setErrors(null),0);
      }
    }
  }

  @HostListener('blur', ['$event'])
  handleBlur(event: any) {
    if (navigator.appVersion && navigator.appVersion.indexOf('.NET') > -1) {
      if (!this.inputBinding._control._value.trim()) {
        // handle blur event
      }
    }
  }
}

When user clicks on input field, somewhere from angular's valueAccessor.onValueChanges(), that field is marked as dirty, using control.markAsDirty().

I have added setTimeout() as well, but it gets executed after markAsDirty() is executed which causes little fluctuation in UI (dirty true -> dirty false).

Can this behavior will be tackled with any other approach? Is there any way to override onValueChanges() because internally it is setting the field to dirty. Adding other libraries (like placeholder.js) is not desired.

n1stre
  • 5,856
  • 4
  • 20
  • 41
Awadhoot
  • 737
  • 6
  • 19
  • This seems to be related to a bug. It's already reported in angular repo: https://github.com/angular/angular/issues/17951 You can use modify this answer to fix this problem: https://stackoverflow.com/questions/33866824/angular2-formcontrol-validation-on-blur/42150151#42150151 – nircraft Nov 09 '18 at 16:41

1 Answers1

2

I customized the pristine as below:

ts file

iePristine: boolean = true;
pincodeCtrl = <formControl>this.form.get('pincode')
  setPlaceholder() {
    const placeholder = 'Enter Code';
    if (this.pincodeCtrl.value) {
      this.iePristine = false;
    }
    if (this.iePristine) {
      this.pincodeCtrl.markAsPristine();
    }
    return placeholder;
  }

isInvalidControl(control: FormControl) {
    return control.invalid && (control.dirty || control.touched);
  }

html file

<input type="text" [placeholder]="setPlaceholder()" formControlName="pincode"
            [ngClass]="isInvalidControl(pincodeCtrl) ? 'form-control text-center is-invalid' : 'form-control text-center'" />
Spears
  • 2,102
  • 1
  • 17
  • 27