ng2-select icon indicating copy to clipboard operation
ng2-select copied to clipboard

Remote call: Items array doesn't update the view

Open dave0688 opened this issue 7 years ago • 3 comments
trafficstars

I have an issue with ng2-select and remote calls: When I type something, my service fetches new items according to the search string. The [items] array is getting updated properly, however the ui is not showing the updated list. Instead, it disappears. Then, when I focusout, the dropdown shows the correct options.

Please see my template here:

	<ng-select
	  #select 
	  [allowClear]="'true'"
	  id="DropdownTypeaheadQuestion-{{ question.id }}"
	  [(items)]="items"
	  [formControl]="formControlToUse"
	  placeholder="{{ placeholderText }}"
	  [multiple]="isMultiple"
	  (selected)="execSelected($event)"
	  (typed)="execKeypress($event)">
	</ng-select>
	<i class="fa fa-spinner fa-pulse fa-3x fa-fw font-size-160 loading-icon" *ngIf="loadingResults"></i>

Here's the controller (relevant methods only):

  execKeypress($event) {
    // When remote, clear all items directly on keypress. Else we have an ugly lag because of the debounce time.
    if (this.config.remote === true) {
      this.items = [];
    }
    this.searchSubject.next($event);
  }
// Inside ngOnInit I subscribe to the observable
    this.searchSubject.debounceTime(500)
                      .takeUntil(this.ngUnsubscribe)
                      .subscribe( (searchTextValue: string) => {

      // save search string on scope
      this.searchTextValue = searchTextValue;
      this.config.httpParams = this.config.httpParams.set('search', searchTextValue);

      // only send search if more than x chars (or empty)
      if (searchTextValue === '' || searchTextValue.length >= this.config.minChars) {
        this.fetchResults();
      }
    });
// fetchResult method fetches the new items and appends them to the items array
this.httpClient.get(url, {params: this.config.httpParams})
                   .takeUntil(this.ngUnsubscribe)
                   .subscribe( (res: any) => {

                     this.items = this.transformSelectableValuesToConsumables(res);
                     
                     this.select.items = this.items;

                     this.loadingResults = false;
                   },
                   (error) => {
                     this.loadingResults = false;

                     // TODO: Implement proper error handling
                   });

I see that the items array is properly filled, but it's not getting refreshed in the UI. Any help is greatly appreciated! :)

dave0688 avatar Jan 15 '18 16:01 dave0688

As far as I know, items property cannot be two-way binding but maybe i'm mistaken. I would replace the [(items)] into [items]. Also i suggest you return the http call as observable to your component and subscribe it from there.

shayl29 avatar Jan 16 '18 14:01 shayl29

Hi. It was fixed in that fork: https://github.com/optimistex/ng2-select-ex The fork supported with lazy loading of items. Look at this: https://github.com/optimistex/ng2-select-ex/blob/ce8b464dcfdf7e0a1d01b7bb0d2e8660576e31a9/src/ngx-select/ngx-select.component.spec.ts#L808-L839

If you will need more examples text me. I have similar functionality in my different project.

optimistex avatar Jan 25 '18 01:01 optimistex

Hi @dave0688,

I've encountered same problem with my app and didn't wanted to change plugin. So after some research and readings I solved it like this;

// service

`/**

  • customerSearch - search customers by name and type
  • @param customerType string customer type (CANDIDATE, DOMESTIC_CUSTOMER, FOREIGN_CUSTOMER, OTHER, PLUG_CUSTOMER, OTHER, SUPPLIER)
  • @param customerName string customer name
  • @param matchMode string, default = "STARTS_WITH" */

customerSearch(customerType: string, customerName: string, matchMode: string = 'STARTS_WITH'): Observable { const httpParams = new HttpParams().set('matchMode', matchMode).set('customerType', customerType).set('name', customerName);

const httpOptions = {
  observe: 'response' as 'response',
  withCredentials: true,
  params: httpParams
};

console.log(httpParams);

return this.http.get<any>(`${this.API_URL}/customer-search`, httpOptions);

}`

// component.ts

`searchCustomer(event, customerType, supplierType: null | string = '') { const customerName = event.term; this.customerService.customerSearch(customerType, customerName).subscribe((data) => { // this.insuranceCustomerData = data.body;

  if (customerType === 'SUPPLIER' && supplierType !== null) {

    if (supplierType === 'transport') {
      this.transportCustomerData = data.body;
    } else if (supplierType === 'insurance') {
      this.insuranceCustomerData = data.body;
    }

  }

});

}`

// template.html

<div class="form-group row"> <label class="col-sm-4 col-form-label">Sigorta Firması</label> <div class="col-sm-8"> <ng-select placeholder="Müşteri arama..." [items]="insuranceCustomerData" bindLabel="firmName" bindValue="id" (search)="searchCustomer($event, 'SUPPLIER', 'insurance')"> </ng-select> </div> </div>

and see the result (before search, no inital data)

image

after key press search;

image

hope it works for you too ! :)

mrmercc avatar Jul 14 '19 17:07 mrmercc