Model driven forms - input placeholder issue on IE

2019-04-10 05:50发布

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.

1条回答
在下西门庆
2楼-- · 2019-04-10 05:58

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'" />
查看更多
登录 后发表回答