【问题标题】:touched/untouched not updating in custom input component - Angular 2触摸/未触摸未在自定义输入组件中更新 - Angular 2
【发布时间】:2016-11-21 16:59:41
【问题描述】:

我有一个自定义输入组件,它正在更新验证和状态,但已触摸/未触摸。其他所有状态(原始/脏)都按预期工作。

这是一个笨蛋:https://plnkr.co/edit/O9KWzwhjvySnXd7vyo71

import { Component, OnInit, Input, ElementRef, forwardRef, Renderer } from '@angular/core';
import { REACTIVE_FORM_DIRECTIVES, Validator, Validators, NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms';



export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = /*@ts2dart_const*/ {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => CustomInputComponent),
  multi: true
};

const noop = () => {};

@Component({
  selector: 'my-custom-input',
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR],
  template: `
  <div class="form-group">
    <label>CUSTOM INPUT</label>
    <input type="text" class="form-control" [(ngModel)]="value" required>
    <p *ngIf="control.errors.required && control.touched">Field is required</p>
    <strong>Has input been touched: {{control.touched ? 'Yes' : 'No'}}</strong><br>
    <strong>Is input untouched: {{control.untouched ? 'Yes' : 'No'}}</strong><br>
    <strong>Is input dirty: {{control.dirty ? 'Yes' : 'No'}}</strong> <br>
        <strong>Is input pristine: {{control.pristine ? 'Yes' : 'No'}}</strong>
  </div>
  <div>
    In Custom Component: {{value}}
  </div>
`
})


export class CustomInputComponent implements ControlValueAccessor {
  @Input() control;


  // The internal data model
  private _value: any = '';

  //Placeholders for the callbacks
  private _onTouchedCallback: (_:any) => void = noop;

  private _onChangeCallback: (_:any) => void = noop;

  //get accessor
  get value(): any { return this._value; };

  //set accessor including call the onchange callback
  set value(v: any) {
    if (v !== this._value) {
      this._value = v;
      this._onChangeCallback(v);
    }
  }

  //Set touched on blur
  onTouched(){
    this._onTouchedCallback(null);
  }

  //From ControlValueAccessor interface
  writeValue(value: any) {
    this._value = value;
  }

  //From ControlValueAccessor interface
  registerOnChange(fn: any) {
    this._onChangeCallback = fn;
  }

  //From ControlValueAccessor interface
  registerOnTouched(fn: any) {
    this._onTouchedCallback = fn;
  }

}

感谢您的帮助!

【问题讨论】:

    标签: angular angular2-forms


    【解决方案1】:

    刚刚踩到@sharpmachine 答案,它帮助解决了我的问题。我只是想改进它:

    不必在模板级别将blur 事件绑定到onTouched()(这可能容易出错),而是可以将ControlValueAccessor 公开为Directive 并在那里绑定事件。

    import { Directive, forwardRef } from '@angular/core';
    import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
    
    export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomInputAccessor),
      multi: true
    };
    
    @Directive({
      selector: 'my-custom-input',
      host: {'(blur)': 'onTouched($event)'},
      providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR],
    })
    export class CustomInputAccessor implements ControlValueAccessor {
    
      // The internal data model
      private _value: any = '';
    
      public onChange: any = (_) => { /*Empty*/ }
      public onTouched: any = () => { /*Empty*/ }
    
      get value(): any { return this._value; };
    
      set value(v: any) {
        if (v !== this._value) {
          this._value = v;
          this.onChange(v);
        }
      }
    
      writeValue(value: any) {
        this._value = value;
      }
    
      registerOnChange(fn: any) {
        this.onChange = fn;
      }
    
      registerOnTouched(fn: any) {
        this.onTouched = fn;
      }
    }
    

    这样你应该可以使用组件,而不必每次使用它时都绑定blur事件。

    希望对你有帮助!

    【讨论】:

    • 谢谢!很有帮助!
    【解决方案2】:

    我犯了两个错误,就像一个圆头。所以模板需要是:

    <div class="form-group">
        <label>CUSTOM INPUT</label>
        <input type="text" class="form-control" [(ngModel)]="value" (blur)="onTouched($event)" required>
        <p *ngIf="control?.errors?.required && control?.touched">Field is required</p>
    
        <strong>Has input been touched: {{control.touched ? 'Yes' : 'No'}}</strong><br>
        <strong>Is input untouched: {{control.untouched ? 'Yes' : 'No'}}</strong><br>
        <strong>Is input dirty: {{control.dirty ? 'Yes' : 'No'}}</strong> <br>
        <strong>Is input pristine: {{control.pristine ? 'Yes' : 'No'}}</strong>
      </div>
      <div>
        In Custom Component: {{value}}
      </div>
    

    所以输入上的(blur)="onTouched($event)"&lt;p *ngIf="control?.errors?.required &amp;&amp; control?.touched"&gt; 的两件事

    【讨论】:

    • 当然!出于某种原因,我认为实现 ControlValueAccessor 接口将为我解决这个问题。嗯。
    猜你喜欢
    • 1970-01-01
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多