3

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> 

5

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

1 Comment

thanks for your effort. It will solve my problem in another way. thanks again.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.