本文介绍了Angular-未调用controlValueAccessor方法writeValue()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Angular版本:6.1

Angular Version: 6.1

我正尝试使用Kara Erickson所谓的Composite ControlValueAccessor来实现自定义控件,如演示文稿所示, Angular Forms – Kara Erickson – AngularConnect 2017 .控件的值应设置为两个子输入值之一.

I'm trying to implement a custom control using what Kara Erickson is calling a Composite ControlValueAccessor as shown in the presentation, Angular Forms – Kara Erickson – AngularConnect 2017. The control's value should be set to one of the two child input values.

问题是writeValue()似乎仅在最初被调用,而在进一步的值更改时不被调用.

The issue is writeValue() seems to only be called initially and not on further value changes.

这是一个 stackblitz演示.

<form #f="ngForm" (ngSubmit)="f.form.valid && Submit(f)">
    <confirm-password name='password' ngModel #pwd='ngModel'></confirm-password>
    <div>{{pwd.status}}</div>
</form>

confirm-password.html

<div [formGroup]='pass'>
  <label>Password:
    <input type="password" formControlName='pwd1' (blur)='onTouched()'>
  </label>
  <div *ngIf="controlDir.touched && controlDir.control.errors?.required" 
         class="error">Password is required.</div>

  <label>Please re-enter password:
    <input type="password" formControlName='pwd2' (blur)='onTouched()'>
  </label>
  <div class='error' *ngIf='controlDir.touched && controlDir.control.errors?.notEqual && 
                            !controlDir.errors?.required'>Passwords do not match.</div>
</div>

confirm-password.ts

import { Component, Self, OnInit, OnDestroy } from '@angular/core';
import { ControlValueAccessor, AbstractControl, NgControl,
         ValidatorFn, Validators, FormGroup, FormControl } from '@angular/forms';
import { Subscription } from 'rxjs';

@Component({
  selector: 'confirm-password',
  templateUrl: './confirm-password.component.html',
  styleUrls: ['./confirm-password.component.css']
})
export class ConfirmPasswordComponent implements ControlValueAccessor, OnInit, OnDestroy
{
  password: string; // the value of the control should be set to this value
  pass = new FormGroup({
    pwd1: new FormControl(),
    pwd2: new FormControl()
  });
  private onChange: (value: string) => void;
  private onTouched: (value: string) => void;
  private valueChanges: Subscription;

  constructor(@Self() public controlDir: NgControl)
  {
    controlDir.valueAccessor = this;
  }

  ngOnInit()
  {
    const control = this.controlDir.control;

    let myValidators = [
            Validators.required, 
            equalValidator(this.pass.controls.pwd1,
                           this.pass.controls.pwd2)
        ]
    // ovoid overwriting any existing validators
    let validators = control.validator
      ? [control.validator, ...myValidators]
      : [...myValidators];
    control.setValidators(validators);
    control.updateValueAndValidity();
  }

  writeValue(val: any)
  {
    /* whether everything inside of this method is commented out or not 
       doesn't seem to affect anything */
    console.log(val);
    //val && this.pass.setValue(val, {emitEvent: false});
    this.password = val;
  }

  registerOnChange(fn: (val: any) => void)
  {
    this.valueChanges = this.pass.valueChanges.subscribe(fn);
  }

  registerOnTouched(fn: () => void)
  {
    this.onTouched = fn;
  }

  setDisabledState(disabled: boolean)
  {
    disabled ? this.pass.disable() : this.pass.enable();
  }

  ngOnDestroy()
  {
    this.valueChanges.unsubscribe();
  }

}

export function equalValidator(el1, el2): ValidatorFn
{
  return (ctrl: AbstractControl): {[key: string]: any} | null => {
    const notEqual = el1.value !== el2.value;

    return notEqual ?  {"notEqual": true} : null;
  };
}

推荐答案

writeValue在您更改控件值(例如通过设置支持的ngModel属性或控件值)而不是通过用户输入时被调用.

writeValue is called when you are changing control value (eg by setting backing ngModel property or controll value) not by user input.

https://stackblitz.com/edit/angular-hu2bfs?file=src/app/app.app.module.ts

我已删除了因误用ngModel

如您所见,如果您输入intu额外的输入新值并按下按钮,则会调用writeValue.

As you can see, if you type in intu extra input new value and push the button, writeValue is called.

进行包装-当控制器更改模型值时调用writeValue,而writeValue的目的是做必要的工作,以反映通过自定义控件进行的模型更改.

to wrap it up - writeValue is called when controller changes model value, and writeValue purpose is to do required stuff to reflect model changes by custom control.

这篇关于Angular-未调用controlValueAccessor方法writeValue()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 12:43