触摸/未触摸未在自定义输入组件中更新 - Angular 2 [英] touched/untouched not updating in custom input component - Angular 2

查看:27
本文介绍了触摸/未触摸未在自定义输入组件中更新 - Angular 2的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这是一个 plunker: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';导出 const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any =/*@ts2dart_const*/{提供:NG_VALUE_ACCESSOR,useExisting: forwardRef(() => CustomInputComponent),多:真};const noop = () =>{};@成分({选择器:'我的自定义输入',提供者:[CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR],模板:`<div class="form-group"><label>自定义输入</label><input type="text" class="form-control" [(ngModel)]="value" required><p *ngIf="control.errors.required && control.touched">必填字段</p><strong>输入是否被触摸:{{control.touched ?是":否"}}</strong><br><strong>输入是否不变:{{control.untouched ?是":否"}}</strong><br><strong>输入是否脏:{{control.dirty ?'是' : '否'}}</strong><br><strong>输入是否原始:{{control.pristine ?'是' : '否'}}</strong>

<div>在自定义组件中:{{value}}

`})导出类 CustomInputComponent 实现 ControlValueAccessor {@Input() 控件;//内部数据模型私有_值:任何 = '';//回调占位符私人 _onTouchedCallback: (_:any) =>void = noop;私人 _onChangeCallback: (_:any) =>void = noop;//获取访问器get value(): any { return this._value;};//设置访问器包括调用onchange回调设置值(v:任何){如果 (v !== this._value) {this._value = v;this._onChangeCallback(v);}}//设置触摸模糊onTouched(){this._onTouchedCallback(null);}//来自ControlValueAccessor接口写值(值:任何){this._value = 值;}//来自ControlValueAccessor接口registerOnChange(fn: 任何) {this._onChangeCallback = fn;}//来自ControlValueAccessor接口registerOnTouched(fn: any) {this._onTouchedCallback = fn;}}

感谢您的帮助!

解决方案

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

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

import { Directive, forwardRef } from '@angular/core';从@angular/forms"导入 { ControlValueAccessor, NG_VALUE_ACCESSOR };导出 const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {提供:NG_VALUE_ACCESSOR,useExisting: forwardRef(() => CustomInputAccessor),多:真};@指示({选择器:'我的自定义输入',主持人:{'(模糊)':'onTouched($event)'},提供者:[CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR],})导出类 CustomInputAccessor 实现 ControlValueAccessor {//内部数据模型私有_值:任何 = '';公共 onChange: any = (_) =>{/*空的*/}公开 onTouched: any = () =>{/*空的*/}get value(): any { return this._value;};设置值(v:任何){如果 (v !== this._value) {this._value = v;this.onChange(v);}}写值(值:任何){this._value = 值;}registerOnChange(fn: 任何) {this.onChange = fn;}registerOnTouched(fn: any) {this.onTouched = fn;}}

这样你应该能够使用组件,而不必每次使用它时都绑定 blur 事件.

希望有帮助!

I have a custom input component that is updating validation and states with the exception of touched/untouched. Everything else state-wise (pristine/dirty) works as expected.

Here's a plunker: 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;
  }

}

Thanks for any help!

解决方案

Just stepped on @sharpmachine answer and it helped to solve my problem. I just would like to improve it:

Instead of having to bind the blur event to onTouched() at the template level (which can be error-prone) it is possible to expose the ControlValueAccessor as a Directive and bind the event there.

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;
  }
}

This way you should be able to use the component without having to bind the blur event each time you use it.

Hope it helps!

这篇关于触摸/未触摸未在自定义输入组件中更新 - Angular 2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆