Learner.123
Learner.123

Reputation: 177

PrimeNG autocomplete dropdown toggle not working as expected

I am working with primeNG autocomplete dropdown. I have followed everything that is there in the docs.Their toggle seems to work fine but not mine.For me the first time I click on the dropdown button it displays the suggestions panel but doesn't hide it when I click again.This is when I have not added an onDropdDownClick event,as it is there in the docs.

app.component.html (without onDropdDownClick event)

     <p-autoComplete [(ngModel)]="RecordName" [suggestions]="filteredRecords" [dropdown]="true" [minLength]="0" [appendTo]="body"
            (completeMethod)="filterRecord($event)" [immutable]="false"
            forceSelection="true" placeholder="Enter record name..." autoHighlight="35" tabindex="0"></p-autoComplete>

app.component.ts

 filterRecord(event:any) {

    this.filteredRecords= [];

    for (let i = 0; i < this.recordsList.length; i++) {
        let record= this.recordsList[i];

        if (record.toLowerCase().indexOf(event.query.toLowerCase()) >= 0) {
        this.filteredRecords.push(record);
         }
    }

}

}

However when I add the Ondropdownclick event the toggle works fine but only once.The first time I click it displays the suggestions dropdown and hides it on the second click,but the third time I click it to display the suggestions again the data doesn't show. Below is the code for this one:

app.component.html

      <p-autoComplete [(ngModel)]="RecordName" [suggestions]="filteredRecords" [dropdown]="true" [minLength]="0" [appendTo]="body"
            (completeMethod)="filterRecord($event)" (onDropdownClick)="onDropDownClick($event)" [immutable]="false"
            forceSelection="true" placeholder="Enter record name..." autoHighlight="35" tabindex="0"></p-autoComplete>

app.component.ts

    filterRecord(event:any) {

    this.filteredRecords= [];

    for (let i = 0; i < this.recordsList.length; i++) {
        let record= this.recordsList[i];

        if (record.toLowerCase().indexOf(event.query.toLowerCase()) >= 0) {
        this.filteredRecords.push(record);
         }
    }

}

onDropDownClick(event: any) {

    this.filteredRecords= this.recordsList;

    event.originalEvent.preventDefault();
    event.originalEvent.stopPropagation();

    if (this.autoCompleteComponent.overlayVisible) {
        this.autoCompleteComponent.hide();
     } else {
        this.autoCompleteComponent.show();
     }

}

For the onDropDownClick event I have also tried the following:

   onDropDownClick(event: any) {

this.filteredRecords=[]
this.filteredRecords= this.recordsList;

event.originalEvent.preventDefault();
event.originalEvent.stopPropagation();

if (this.autoCompleteComponent.overlayVisible) {
    this.autoCompleteComponent.hide();
 } else {
    this.autoCompleteComponent.show();
 }

and also:

     onDropDownClick(event: any) {

          this.filteredRecords=[]

         setTimeout(() => {
        this.filteredRecords= this.recordsList;
            }, 100)

           event.originalEvent.preventDefault();
           event.originalEvent.stopPropagation();

          if (this.autoCompleteComponent.overlayVisible) {
               this.autoCompleteComponent.hide();
                 } else {
             this.autoCompleteComponent.show();
           }

Doesn't work either,The second one just stops displaying the suggestions at all.

Also the this.recordsList gets it data from a service, and while debugging I found that the recordsList has data all of the time,so there doesn't seem to be an issue with that.

Any help would be appreciated.Thankyou!

Upvotes: 0

Views: 6005

Answers (3)

Nitesh Kumar
Nitesh Kumar

Reputation: 1

I have the temporary fix for this issue:- in your html add this 2 function

public setAutoDropdown:boolean=true
onDropDownClick(event:any) {
  this.setAutoDropdown=false
  let data = document.getElementById(event.el.nativeElement.id);
  data.getElementsByTagName('input')[0].setAttribute('readonly','true')

}
getInputData(event:any) {
  console.log(event.el.nativeElement.id);
  if(!this.setAutoDropdown){
  this.setAutoDropdown=true
  }else{
    let data = document.getElementById(event.el.nativeElement.id);
  data.getElementsByTagName('input')[0].removeAttribute('readonly')
  }
}
<p-autocomplete #auto1 (onDropdownClick)="onDropDownClick(auto1)"
    (click)="getInputData(auto1)"></p-autocomplete>

Again it's a Temporary Fix....

Upvotes: 0

Ivan Vrbovčan
Ivan Vrbovčan

Reputation: 21

I had a similar problem and I found that the problem is in the completeMethod handler. You should assign a value to the suggestion variable only once, as a change to that variable will initiate a change detection process.

In this example, the method filterRecord assigns a value to the variable this.filterRecords before the loop, and in the loop:

 filterRecord(event:any) {

    this.filteredRecords=[];
    for (let i = 0; i < this.recordsList.length; i++) {
       let record= this.recordsList[i];

       if (record.toLowerCase().indexOf(event.query.toLowerCase()) >= 0) {
          this.filteredRecords.push(record);
        }
    }
  }

The AutoComplete control starts with the internal method handleSuggestionChange immediately after the value of the variable this.filteredRecords is changed - and this is after the first assignment this.filteredRecords=[];. At that moment, the suggestion list is empty, and the overlay is not shown.

To correct this, the array should be prepared in advance, and then assigned to a variable. In this example, a temp variable can be used:

 filterRecord(event:any) {

    const tempFilteredRecords=[];
    for (let i = 0; i < this.recordsList.length; i++) {
       let record= this.recordsList[i];

       if (record.toLowerCase().indexOf(event.query.toLowerCase()) >= 0) {
          tempFilteredRecords.push(record);
        }
    }
    this.filteredRecords = tempFilteredRecords; 
  }

Upvotes: 2

Kiril Nikiforov
Kiril Nikiforov

Reputation: 11

I know it's late but after the rest hitting this point this worked for me:

onDropDownClick(event: any) {
    event.originalEvent.preventDefault();
    event.originalEvent.stopPropagation();

    if (this.autoCompleteObject.panelVisible) {
        setTimeout(() => {
            this.autoCompleteObject.hide();
        }, 100)
     } else {
        setTimeout(() => {
            this.autoCompleteObject.show();
        }, 100)
     } 
}

Upvotes: 1

Related Questions