Ayush Nair
Ayush Nair

Reputation: 93

Angular Reactive Forms data change validation not cosmetic change validation

Given a particular formGroup and it's corresponding HTML form

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

Consider the scenario that fieldName = "WORKFORCE". In the HTML Form, I edit the input field to make the value first "WORKFORCE_1" and then back to "WORKFORCE". The formGroup attributes have changed from pristine=true, dirty=false, touched=false to pristine=false, dirty=true, touched=true.

Hence the form is valid. But actually no data change has taken place. Are there any inbuilt FormControl or FormGroup attributes or any combination thereof that can help me disable the "UPDATE" button or can I do such validation only after the fact(UPDATE button click)?

Can I create a custom validator to address this validation logic?

Upvotes: 0

Views: 1247

Answers (1)

Eliseo
Eliseo

Reputation: 58099

You can create a custom validator "isDifferent", but first reemplace the way to create the form using a function

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

You use as

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

Update:Aclaration. Well the code above goes from I imagine a typical REST. So if we has a component to Edit/Create a register we has a router like

{ path: 'hero/:id',component: HeroDetailComponent },

Where, possible id values are a number or "new", so we can has

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

Our component, that has an form and use reactiveForm take account this, so

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

Our .html needn't a complex handlers in inputs, e.g. our button "submit" can be

<!--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>

Upvotes: 1

Related Questions