Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate duplicate entry in angular form builder array?

I am using angular6 reactive form with form builder and form array. I am facing problem with duplicate subject entry from drop down in form array. How to validate to avoid duplicate entry in from array.

I have a subject list with drop down. When i click on add button then a subject array will add. If i add similar subject it also be added. But i want to avoid duplicate subject entry. When i entry duplicate subject then a validation message will show and save button will disable.

stackblitz

ts code

 olevelSubForm = this.fb.group({
   olevelSubArray: this.fb.array([
    ])
  });

 olevelSubjectList: any = [ 'Geography','Mathematics', 
 'Physics','Chemistry'];

 constructor(private fb: FormBuilder) {}

 ngOnInit() {
   this.addItemOlevel();
 }

 // olevel
 createOlevelSub(): FormGroup {
    return this.fb.group( {
        olevelSubject: new FormControl('', Validators.compose(
            [
                Validators.required
            ]
        )),
    });
  }

 addItemOlevel() {
    const control = <FormArray>this.olevelSubForm.controls.olevelSubArray;
    control.push(this.createOlevelSub());
 }

 saveData() {
  console.log('saved')
 }

html code

 <form [formGroup]="olevelSubForm" >
  <div formArrayName="olevelSubArray">
   <table>
    <thead>
      <tr style="font-size: 15px;">
       <th>Subject</th>
      </tr>
    </thead>
      <tbody>

       <tr *ngFor="let item of olevelSubForm.get('olevelSubArray').controls; let i = index;" [formGroupName]="i">
         <td>
          <select formControlName="olevelSubject">
            <option *ngFor="let olevelSub of olevelSubjectList" [value]="olevelSub">{{ olevelSub }}</option>
          </select>
         </td>
         <td>
            <button style="float: right" [disabled]="olevelSubForm.invalid"(click)="addItemOlevel()"> Add
          </button>
         </td>
       </tr>

    </tbody>
  </table>
   <button [disabled]="olevelSubForm.invalid"(click)=saveData()>Save</button>
    <pre> {{ olevelSubForm.value | json }} </pre>
  </div>

like image 452
Monir Tuhin Avatar asked Sep 11 '26 01:09

Monir Tuhin


1 Answers

In my comment I put and answer with a different aproach: that the options you can select was different in each level, so you can not choose some yet choosed. that, if you has a function like

getSubjectForFormArray(i, olevelSubjectList) {
    return i == 0 ? olevelSubjectList :
      this.getSubjectForFormArray(i - 1, olevelSubjectList.filter(x => 
           x != this.olevelSubForm.get('olevelSubArray').value[i-1].olevelSubject))
  }

Yes is a recursive function that begins with all the options and in each step, remove from the list the value we are choose. So, your option list can be like

<option *ngFor="let olevelSub of getSubjectForFormArray(i, olevelSubjectList)"
   [value]="olevelSub">{{ olevelSub }}</option>

Anyway, this dont' avoid that if, e.g we choose "Mathematics","Chemistry", if change the first combo to Chemistry, we'll get two "Chemistry". So, we are going to check each change of the array. That's in ngOnInit

this.olevelSubForm.get('olevelSubArray').valueChanges.subscribe(res=>{
  res.forEach((x,index)=>{
    //res is the value of the array,e.g. -in one moment- 
    //[{olevelSubject:'Mathematics'},{olevelSubject:'Chemistry'},{olevelSubject:null}]
    if (index)
    {
      //before becomes an array with the values selected before, eg.  -in one moment-
      //   ['Mathematics','Chemistry']
      const before=res.slice(0,index).map(x=>x.olevelSubject)
      if (before.find(x=>x==res[index].olevelSubject))
      {    
          (this.olevelSubForm.get('olevelSubArray') as FormArray)
            .at(index).setValue({olevelSubject:null})
      }
    }
  })
})

See the stackblitz

like image 109
Eliseo Avatar answered Sep 13 '26 17:09

Eliseo