Angular Reactive Forms 数据更改验证不是外观更改验证

Angular Reactive Forms data change validation not cosmetic change validation

给定一个特定的 formGroup 及其对应的 HTML 表单

this.fieldForm = new FormGroup({
      fieldId: new FormControl(null),
      fieldName: new FormControl("", Validators.required),
      sourceCreateBy: new FormControl(null),
      sourceUpdateBy: new FormControl(null),
    }, {validators: FieldFormValidators.invalidFormInput})  // some other logic

考虑 fieldName = "WORKFORCE" 的场景。在 HTML 表单中,我编辑输入字段以首先将值设置为“WORKFORCE_1”,然后返回“WORKFORCE”。 formGroup 属性已从 pristine=true, dirty=false, touched=false 更改为 pristine=false, dirty=true, touched=true

因此表格有效。但实际上并没有发生数据变化。是否有任何内置的 FormControlFormGroup 属性或其任意组合可以帮助我禁用“更新”按钮,或者我只能在之后进行此类验证事实(点击更新按钮)?

我可以创建一个自定义验证器来处理这个验证逻辑吗?

您可以创建自定义验证器“isDifferent”,但首先要重新使用函数创建表单的方式

getForm(data:any=null){
  data=data|| {fieldID:null,fieldName:"",sourceCreateBy:null,sourceUpdateBy:null}
  return FormGroup({
      fieldId: new FormControl(null),
      fieldName: new FormControl("", Validators.required),
      sourceCreateBy: new FormControl(null),
      sourceUpdateBy: new FormControl(null),
    }, {validators: [FieldFormValidators.invalidFormInput,isDifferent(data)]}) 
getForm(data:any=null){
  data=data|| {fieldID:null,fieldName:"",sourceCreateBy:null,sourceUpdateBy:null}
  return FormGroup({
      fieldId: new FormControl(data.fieldID),
      fieldName: new FormControl(data.fieldName, Validators.required),
      sourceCreateBy: new FormControl(data.sourceCreatedBy),
      sourceUpdateBy: new FormControl(data.sourceUpdateBy),
    }, {validators: [FieldFormValidators.invalidFormInput,isDifferent(data)]})  // some other logic

isDiferent(data:any){
   return (control:AbtractControl)=>{
     bool equal=true;
     Object.keys(data).forEach(key=>{
        equal=equal && data[key]==control.value[key]
     })
     return equal?{error:"must be different"}:null
   }
}

你用作

this.fieldForm=this.getForm(..your object...)

更新:声明。好吧,上面的代码来自我想象的典型 REST。因此,如果我们有一个 Edit/Create 寄存器的组件,我们就有一个像

这样的路由器
{ path: 'hero/:id',component: HeroDetailComponent },

其中,可能的 id 值是数字或“新”,因此我们可以

url=hero/new  //edit-component to create a new "hero"
url=hero/1    //edit-compoent to edit the hero with "id=1"

我们的组件,有一个表单并使用 reactiveForm 考虑到这一点,所以

constructor(private activatedRoute: ActivatedRoute,private service: HeroService) {}
form:FormGroup
status:string //here we store if "new" or "edit" to use for e.g.
              //the button "submit" show a message "create" or "update"
ngOnInit() {
  this.activatedRoute.paramMap.pipe(
    switchMap(params => {
      const id=params.get('id')
      if (id=="new"){
          this.form=this.getForm();  //create a empty form
          this.status="new"
      }
      else{
         //use "+id" to convert to number the "id"
         this.service.getHeroe(+id).subscribe(res=>{
             //here we has the "data of the "hero"
             this.form=this.getForm(res)  //create a form with the data of hero
             this.status="edit"
         })
      }
  );
}

我们的 .html 不需要复杂的输入处理程序,例如我们的按钮“提交”可以是

<!--see that the button is disabled if the form is invalid
    if it's not invalid you need equal "disabled" to null,
    **not** to false
--->

<button disabled="form.invalid?true:null">
     {{status=="new"?"Create":"Update"}}
</button>