0

长话短说,我目前正在研究一个指令,该指令在修改时将函数应用于控制值。该功能仅在模型侧修改控制值。是这样的:

// import ...

// @Directive
export class ControlValuePipeDirective implements OnInit{

  @Input() ngxControlValuePipe?: (value? :any) => any;

  constructor(
    private ngControl: NgControl
  ) {}

  ngOnInit(): void {
    if (this.ngxControlValuePipe === undefined) {
      console.info("No method was provided to the ngxControlValuePipe directive. Ignoring it.")
    }else{
      this.ngControl.valueAccessor?.registerOnChange((value: any) => {
          this.ngControl.control?.patchValue(this.ngxControlValuePipe ?
            this.ngxControlValuePipe(value) : value,
            {emitModelToViewChange: false})
        }
      )
    }
  }
}

我遇到的问题是当我将验证器添加到这样的控件时:

// import ...

// @Component
export class AppComponent {
  public profileForm: FormGroup;

  constructor() {
    const streetControl = new FormControl('', [Validators.maxLength(10)]);
    // this.profileForm = ...
  }

  public editValueOnTheFly(value: any): any{
    return value + ' this more than ten chars length string';
  };
}
<!-- more html -->
<input id="street" type="text" formControlName="street" [ngxControlValuePipe]="editValueOnTheFly">
<!-- more html -->

如果我的 streetControl 控件值在视图中被修改,那么模型会使用该editValueOnTheFly方法进行编辑,该方法会在模型值中添加一个长字符串。这会触发验证并使控件无效,因为新模型值超过 10 个字符。

有什么方法可以对视图中显示的值(未修改)运行验证器?

4

1 回答 1

0

因为您想避免验证由 ControlValuePipeDirective 修改的值,所以我建议您将数据模型和表单模型分开。

ControlValuePipeDirective 不应更新表单的模型:

export class ControlValuePipeDirective implements OnInit{
    ...
    ngOnInit(): void {
        if (!this.ngxControlValuePipe) { return; }

        this.ngControl.valueAccessor?.registerOnChange((value: any) => {
            this.ngxControlValuePipe(value); 
        }
    }
}

AppComponent 的 editValueOnTheFly 将负责 profile 模型更新:

interface ProfileModel {
    street: string;
    ...
}

export class AppComponent {
    public profileForm: FormGroup;
    private profileModel: ProfileModel;
    ...
    public editValueOnTheFly(value: any): any{
        const updatedValue = value + ' this more than ten chars length string';
        this.profileModel = { ...this.profileModel, street: updatedValue };
    }
}

profileModel 字段也可以替换为 Subject,以便能够订阅配置文件模型的更改。

于 2021-07-11T15:25:13.607 回答