Dheeraj Kumar
Dheeraj Kumar

Reputation: 4175

PrimeNg AutoComplete Suggestions are not loading

I am trying to implement PrimeNg AutoComplete control in my project.

I am referring this PrimeNg

These are the steps I have followed.

1. Added Module.

import { AutoCompleteModule } from 'primeng/autocomplete';

2. Imported Module

 imports: [CommonModule, FormsModule, AutoCompleteModule],

3. Created Array of String.

  brands: string[] = ['Audi', 'BMW', 'Fiat', 'Ford', 'Honda', 'Jaguar', 'Mercedes', 'Renault', 'Volvo', 'VW'];

4. Added p-template

    <p-autoComplete [(ngModel)]="brand" [suggestions]="this.brands" (completeMethod)="search($event)" [size]="30 [minlength]="1" placeholder="Tags"></p-autoComplete>

On running project View is loaded but when I start typing in textbox, suggestions are not loading though loading gif is visible.

There is no error at console.

I have looked over all blogs and documentation before asking this but didnt find any solution.

Is there anything I am missing!

Any help is highly appreciated.

Upvotes: 6

Views: 19812

Answers (6)

Stephan
Stephan

Reputation: 594

Here is a solution based on documents and worked for me:

For static values we have to do as following:

In component.ts file:

  suggestions: string[] = []
  brands: string[] = ['Audi', 'BMW', 'Fiat', 'Ford', 'Honda', 'Jaguar', 'Mercedes', 'Renault', 'Volvo', 'VW'];

  ...
  
  getBrands($event) { // to load suggestions
      this.suggestions = Array.from(this.brands)
  }

And in component.html file:

<p-autoComplete formControlName="brand" [suggestions]="suggestions"
                            (completeMethod)="getBrands($event)" ... 
</p-autoComplete>

Upvotes: 0

Pakk
Pakk

Reputation: 1339

Thanks @ Mike Gledhill -> whoms answer should be accepted ... btw

Just wanted to add this as a SINGLE INSTANCE

using

$filtered = new BehaviorSubject([]);

this.$filtered.next([...items]);//This bit assigns new reference to the BehaviorSubject Observable

getItems($event) {
    this._itemsServiceProxy
        .getItems($event.query)
        .subscribe((items: ItemDto[]) => {
         this.$filtered.next([...items]);
        });
}

And I'm consuming it in this way:

[suggestions]="$filtered | async"

[showEmptyMessage]="($filtered | async).length === 0"

(completeMethod)="getItems($event)"

<p-autoComplete name="items" [(ngModel)]="selectedItem"  
    [field]="selectedItemDisplayConverter" [dropdown]="true" forceSelection="true" dataKey="id"
    [placeholder]="l('SearchItemThreeDots')" 
    [suggestions]="$filtered | async"
    [showEmptyMessage]="($filtered | async).length === 0"
    (completeMethod)="getItems($event)"
    [emptyMessage]="l('NoItemsFound')" required [delay]="750">
    <ng-template let-item pTemplate="item">
        <div class="row">
            <div class="col-md-12">
                {{ item.clientName }}<br />
                <a href="javascript:;"><small>{{ item.name }}</small></a>
            </div>
        </div>
    </ng-template>
</p-autoComplete>

for the field i used this method to properly display selected items

selectedItemDisplayConverter(selectedItem: ItemDto) {
    return selectedItem.clientName + ': ' + selectedItem.name;
}

Upvotes: 3

Mike Gledhill
Mike Gledhill

Reputation: 29161

This answer won't solve your particular problem, but it is useful for anyone suffering from Suggestions not appearing when loading them from a web server.

We have a list of 20,000 funds. The user can type in a few characters, and we call a web service to get a list of matches.

This all worked fine, and Chrome's developer tools showed me the results were being loaded.. but nothing was appearing in PrimeNG's suggestions.

Now, the tricky bit...

In my Angular app, if I stored the results in "this.fundSuggestions", it all worked fine.

export class FundComponent {
  fundSuggestions:KeyValue[];
  chosenFund:KeyValue;
  . . .
}

My autocomplete looked like this:

<p-autoComplete 
        [(ngModel)]="chosenFund" 
        [suggestions]="fundSuggestions" 
        (completeMethod)="filterValues($event)" 
        field="value"
        delay="500"
        [dropdown]="false"
        [multiple]="false">
</p-autoComplete>

However, I couldn't do this. My AutoComplete control was actually being created dynamically in a *ngFor loop, and there could be several of these controls on my screen.

I found that the filterValues() function did kick in, it did load the list of values and bind it to the fnd.fundSuggestions array, but the control didn't show any suggestions.

The solution was this... rather than setting [suggestions] to point directly at the fnd.fundSuggestions array, I needed to point it at an observable.

So, in my filterValues() function, I would create an observable using of() :

filterValues(event, fnd) {
    fnd.fundSuggestions = [];
    let searchString = (event.query ?? '').toLowerCase();
    if (searchString.length < 3) {
        return;
    }
    let body = JSON.stringify(searchString);
    let URL = 'https:\\someservice.com\searchForFunds";
    this.mikesService.searchService(URL, body).subscribe(
        data =>  {
            fnd.fundSuggestions = data;
            fnd.observable = of(fnd.fundSuggestions);
        }
    );
}

And I changed my control to get this suggestions from this instead:

<div *ngFor="let fnd of listOfFunds">
  <p-autoComplete 
        [(ngModel)]="fnd.chosenFund" 
        [suggestions]="fnd.observable | async" 
        (completeMethod)="filterValues($event, fnd)" 
        field="value"
        delay="500"
        [dropdown]="false"
        [multiple]="false">
  </p-autoComplete>
</div>

This problem took me ages to fix... I hope this is useful for other developers.

Upvotes: 2

DirtyMind
DirtyMind

Reputation: 2563

I did below to solve my issue. I was using this.result = data. Which was not working so I changed it:

this.backendService.getSiteList(this.query).subscribe(data => {
      this.results = [...data];
  });

Upvotes: 4

Kentonbmax
Kentonbmax

Reputation: 958

I mitigated the issue by re-assigning to .suggestions of the autocomplete object and calling show each time. You may be able to assign this.unfilteredResults directly to .suggestions. I know this is currently working in v6.x.

onDropDown(): void {
  this.filteredResults = [];
  this.filteredResults = this.unfilteredResults;
  this.autoSelectorElement.suggestions = this.filteredResults;
  this.autoSelectorElement.show();
}

Upvotes: 0

Dheeraj Kumar
Dheeraj Kumar

Reputation: 4175

For future references,

Initially I thought (completeMethod) property wont have any effect if I return suggestion array as it is. But what is needed is that Suggestion array must change in fact must have a new reference every time we enter text in textbox.

Below is the snapshot from documentation.

https://www.primefaces.org/primeng/#/autocomplete

Change Detection

AutoComplete either uses setter based checking or ngDoCheck to realize if the suggestions has changed to update the UI. This is configured using the immutable property, when enabled (default) setter based detection is utilized so your changes such as adding or removing a record should always create a new array reference instead of manipulating an existing array as Angular does not trigger setters if the reference does not change. For example, use slice instead of splice when removing an item or use spread operator instead of push method when adding an item. On the other hand, setting immutable property to false removes this restriction by using ngDoCheck with IterableDiffers to listen changes without the need to create a new reference of data. Setter based method is faster however both methods can be used depending on your preference.

Upvotes: 15

Related Questions