Reputation: 4175
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
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
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
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
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
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
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