NileshPatel17 / ng-multiselect-dropdown

Multiple Select Dropdown Component
https://nileshpatel17.github.io/ng-multiselect-dropdown/
327 stars 287 forks source link

Multiselect stopped after update to angular 9 #214

Open giovannidias1 opened 4 years ago

giovannidias1 commented 4 years ago

Angular version:


     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/

Angular CLI: 9.0.4
Node: 12.13.1
OS: win32 x64

Angular: 9.0.4
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.900.4
@angular-devkit/build-angular      0.900.4
@angular-devkit/build-ng-packagr   0.900.4
@angular-devkit/build-optimizer    0.900.4
@angular-devkit/build-webpack      0.900.4
@angular-devkit/core               9.0.4
@angular-devkit/schematics         9.0.4
@angular/cdk                       9.1.0
@angular/material                  9.1.0
@ngtools/webpack                   9.0.4
@schematics/angular                9.0.4
@schematics/update                 0.900.4
ng-packagr                         9.0.2
rxjs                               6.5.4
typescript                         3.6.4
webpack                            4.41.2

ng-multiselect-dropdown version: ng-multiselect-dropdown@0.2.10

Description of issue: After updating angular 9 and the latest version of multi-select some of the mult-selects used stopped working not listing the items. The problem is occurring when using ng if to show a select or when the date is a static variable making the date observable with a timeout works

Steps to reproduce:

Expected result: image

Actual result: image

Demo: Stackblitz running angular 8 https://stackblitz.com/edit/angular-vkrvjz

Not working code

    this.reports.push({
      name: this.translateService.instant('ReportComponent.Users'),
      id: this.reportType.Users
    });
    this.reports.push({
      name: this.translateService.instant('ReportComponent.Courses'),
      id: this.reportType.Course
    });

working code

const reports$ = new Observable(observer => {
      setTimeout(() => {
        const reports = [
          {
            name: this.translateService.instant('ReportComponent.Users'),
            type: this.reportType.Users
          },
          {
            name: this.translateService.instant('ReportComponent.Courses'),
            type: this.reportType.Course
          }]

        observer.next(reports);
        observer.complete();
      }, 1000);

    });

    reports$.subscribe((data) => {
      console.log('data', data)
      this.reports = data;
    })
  }
giovannidias1 commented 4 years ago

After some time I discovered that the problem is in the way the inputs are read because one is called after the other

A workaround to fix the problem was this:

  public set data(value: Array<any>) {
    setTimeout(() => { // <--- add this timeout 
      if (!value) {
        this._data = [];
      } else {
        const firstItem = value[0];
        this._sourceDataType = typeof firstItem;
        this._sourceDataFields = this.getFields(firstItem);
        this._data = value.map((item: any) =>
          typeof item === 'string' || typeof item === 'number'
            ? new ListItem(item)
            : new ListItem({
              id: item[this._settings.idField],
              text: item[this._settings.textField],
              isDisabled: item[this._settings.disabledField]
            })
        );
      }
    }, 1);
  }
Michi-2142 commented 4 years ago

Same problem here...

ErnestManukyan commented 4 years ago

@Michi-2142 there is an issue #216. AndrewTaftPlusone solved the problem by moving settings param prior to the data param.

gnganapath commented 4 years ago

import {IDropdownSettings} from 'ng-multiselect-dropdown'; const reports$ = new Observable(observer => { setTimeout(() => { const reports = [ { name: 'displayName', type: 'key' }, { name: 'displayName', type: 'key' }]

    observer.next(reports);
    observer.complete();
  }, 1000);

});

reports$.subscribe((data) => {
  console.log('data', data)
  this.reports = data;
})

}

 <ng-multiselect-dropdown tabindex="0" (onDeSelect)="unselectType($event)"
                                     (onSelect)="onTypeSelect($event)" [(ngModel)]="selectedType"
                                     [data]="reports"
                                     [placeholder]="'Custom placeholder'" [settings]="dropdownSettingsReportType">
            </ng-multiselect-dropdown>

It's working in Angular 9.0.1 Thanks : https://stackblitz.com/edit/angular-vkrvjz?file=src%2Fapp%2Fapp.component.ts

Michi-2142 commented 4 years ago

@Michi-2142 there is an issue #216. AndrewTaftPlusone solved the problem by moving settings param prior to the data param.

This worked for me, too. Thank you!

rooby commented 4 years ago

Also #207 seems to be the same issue.

rooby commented 4 years ago

I don't think it's necessary to resort to a setTimeout(). ~~That data mapping code should be split out into a separate function and given the appropriate checks to make sure data & settings are both set before trying to use their values. Then that function would be called from the settings setter function as well as the data setter function.~~

Actually that struck out idea won't work, unless the component is also storing the unmodified input data, which is not the current intent.

One solution would be to move to using ngOnChanges instead of setters, that way you will get the values of data and settings at the same time.