Search code examples
angulardropdownangular-reactive-formsmulti-selectangular-ngselect

ng-select: how to select multiple items having same label but different object


I'm trying to patch multiple selected items in ng-select drop down. I have not specified any bindValue, so the items should be bind by object (as specified at https://www.npmjs.com/package/@ng-select/ng-select)

But while trying to do this the items do not get selected depending on the object but by the label displayed. Also only the first label gets selected.

Example: app.component.html

<form [formGroup]="group">
    <div class="form-group" formGroupName="school">
        <ng-select labelForId="school" placeholder="Select school" [items]="schools" formControlName="code"
            bindLabel="displayLabel" multiple="true" groupBy="city">
        </ng-select>
    </div>
</form>

app.component.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  group: FormGroup;
  schools = [];
  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.initSchools();
    const formModel = {
      school: new FormGroup({
        code: new FormControl(null, Validators.required)
      })
    }
    this.group = this.fb.group(formModel);
    this.group.patchValue({
      school: {
        code:
          [
            {
              schoolId: 'SC003',
              displayLabel: 'Test-3 school',
              city: "City1"
            },
            {
              schoolId: 'SC005',
              displayLabel: 'Test-3 school',
              city: "City5"
            }
          ]
      }
    });
  }

  initSchools() {
    this.schools.push(
      {
        schoolId: 'SC001',
        displayLabel: 'Test-1 school',
        city: "City1"
      },
      {
        schoolId: 'SC002',
        displayLabel: 'Test-2 school',
        city: "City2"
      },
      {
        schoolId: 'SC003',
        displayLabel: 'Test-3 school',
        city: "City3"
      },
      {
        schoolId: 'SC004',
        displayLabel: 'Test-4 school',
        city: "City4"
      },
      {
        schoolId: 'SC005',
        displayLabel: 'Test-3 school',
        city: "City5"
      }
    );
  }
}

In the example above only the object for item

    {
      schoolId: 'SC003',
      displayLabel: 'Test-3 school',
      city: "City1"
    },

gets selected,

and the below item does not

    {
      schoolId: 'SC005',
      displayLabel: 'Test-3 school',
      city: "City5"
    }

What should be the way so both the items gets selected in drop down (with provide unique objects). Is any thing missing out here. Any other way to achieve this.

Have example running here : https://stackblitz.com/edit/angular-szel64?file=src%2Fapp%2Fapp.component.ts


Solution

  • Found that there is a compareWith option for ng-select that lets you define a function to compare the objects. Using this you can bind objects and it gets selected depending on the function provided with compareWith option.

    Below are my changes in case anyone lands into same problem

    app.component.html

    <form [formGroup]="group">
        <div class="form-group" formGroupName="school">
            <ng-select labelForId="school" placeholder="Select school" [items]="schools" formControlName="code"
                bindLabel="displayLabel" multiple="true" groupBy="city"
          [compareWith]="compareFunction">
            </ng-select>
        </div>
    </form>
    

    app.component.ts

    ...
      compareFunction(item, selected) {
    // any logic to compare the objects and return true or false
        return item.schoolId === selected.schoolId
      }
    ...