0

I have a class that sets up a FormArray of Product Benefits. This array contains benefitGroupName and benefitSettingName properties. I would like to loop through this array in my html view to display only unique benefitGroupName values, as many of them are duplicates.

export class EditProductsComponent implements OnInit {
    productBenefitSettingForm: FormGroup;
    benefitSettings: FormArray;
    benefitSettingList: BenefitSettingModel[] = [];

    AddBenefitSetting() {
        const control = this.productBenefitSettingForm.controls.benefitSettings as FormArray;
        control.push(this.productBenefitSettingFormGroup());

        this.benefitSettingList.push(new BenefitSettingModel());

        this.counter++;
        this.benefitSettingList[this.counter].benefitSettingId = '';
        this.benefitSettingList[this.counter].benefitGroupId = null;
   }
}

Model:

export class BenefitSettingModel {
  benefitSettingId: string;
  benefitSettingName: string;
  benefitGroupId: number;
  benefitGroupName: string;
}

My view is currently spitting out all benefitGroupName values with an ngFor The logic I believe I need to apply is something like benefitSettingList.benefitGroupName.filter((v, i, a) => a.indexOf(v) === i) to get unique benefitGroupName values but I'm not sure where in my class to do that or how to call it in the view.

<div formArrayName="benefitSettings" *ngFor="let benefitSetting of productBenefitSettingForm.get('benefitSettings')['controls']; let i = index; let last = last">
  {{benefitSettingList[i].benefitGroupName}}
</div>

2 Answers 2

1

Use a pipe:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'unique',
  pure: false
})

export class UniquePipe implements PipeTransform {
    transform(value: any): any{
        if(value!== undefined && value!== null){
            return [...new Set(value)]; ;
        }
        return value;
    }
}

Use it like this:

<ul>
  <li *ngFor="let benefit of this.benefits | unique">
    {{benefit.benefitSettingName}}
  </li>
</ul>
Sign up to request clarification or add additional context in comments.

2 Comments

Could you show me how I would use the pipe in my current ngFor loop?
<ul> <li *ngFor="let benefit of this.benefits | unique"> {{benefit.benefitGroupName}} </li> </ul>
1

To simply remove duplicates based on some property once at the beginning

const newList: BenefitSettingModel[] = [];
this.benefits.forEach((benefit: BenefitSettingModel) => {
  if (!newList.some(x => x.benefitGroupName === benefit.benefitGroupName)) {
    newList.push(benefit);
  }
});

after this you can use this new list to render html elements.

Update

Basically you don't need to modify much just before giving it to Angular you filter it for duplicates:

  ngOnInit() {
    this.productBenefitSettingForm = this.fb.group({
      benefitSettings: this.fb.array([])
    });

    this.dataService.getBenefits()
      .subscribe((receivedBenefits: BenefitSettingModel[]) => {

        // dump received benefits (possibly with duplicates)
        console.log(JSON.stringify(receivedBenefits, null, 2));

        // filter out duplicates
        const newList: BenefitSettingModel[] = [];
        receivedBenefits.forEach((benefit: BenefitSettingModel) => {
          if (!newList.some(x => x.benefitGroupName === benefit.benefitGroupName)) {
            newList.push(benefit);
          }
        });

        // get reference to the form array
        const fa = this.productBenefitSettingForm.controls["benefitSettings"] as FormArray;

        // fill the form with the list (without any duplicates)
        newList.forEach((b: BenefitSettingModel) => {
          fa.push(this.addBenefitSetting(b.benefitSettingId, b.benefitGroupId));
        });
      });
  }

in html:

<form [formGroup]="productBenefitSettingForm">
    <div formArrayName="benefitSettings">
        <div *ngFor="let optionGroup of productBenefitSettingForm.controls['benefitSettings'].controls;  let i=index">
            <div [formGroupName]="i">
                <input type="text" formControlName="benefitSettingId">
                <input type="text" formControlName="benefitGroupId">
          </div>
        </div>
    </div>
</form>

Check this working Stackblitz.

1 Comment

Thanks, could you elaborate on how I would use this new list in my html? How would I modify my ngFor?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.