Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular: autocomplete field changes focus after removing an item

I have an Angular 2 app that uses PrimeNG components.

The UI has autocomplete component with multi-select (p-autoComplete) similar to the one from the documentation:

<p-autoComplete [(ngModel)]="countries" 
                [suggestions]="filteredCountriesMultiple" 
                (completeMethod)="filterCountryMultiple($event)" 
                [minLength]="1" 
                placeholder="Countries" 
                field="name" 
                [multiple]="true">
</p-autoComplete>

The only difference is that in my case the input field has fixed dimensions and scroll bar.

Problem:

Every time when I remove an element from the middle of the autocomplete list it moves focus to the bottom of the input field. It looks like this:

enter image description here

It is very annoying for users, especially when there are several fields that should be removed.

Question: How to force scroll to stay on the same position after removing an element?

How to reproduce:

To be more specific, you can reproduce the issue by adding the next css

max-width: 150px;
max-height: 100px;
overflow-y: auto;

directly on the documentation page into ui-autocomplete-multiple-container.ui-inputtext css class using browser console.

UPDATE: I managed to get the scroller position by setting up onUnselect method in the component using code like this:

onUnselect(event: any) {
    document.querySelector("div.my-input-class").scrollTop
}

UPDATE 2: I managed to make it work

The solution is combination of onUnselect and onFocus event handlers.

First. I save the last scroller position into a field in onUnselect call.

Second. I set this value to the specified element during onFocus call.

The corresponding code looks like this:

scrollPosition: number = 0;

onUnselect(event: any) {
    let input = document.querySelector("div.my-input-class");
    this.scrollPosition = input.scrollTop;
}

onFocus(event: any) {
    let input = document.querySelector("div.my-input-class");
    input.scrollTop = this.scrollPosition;
}

It works well and probably this will be the final solution.

However I don't like it. It would be much better if PrimeNG guys embed such a useful functionality in their component. For me it is strange why doesn't it come out of the box.

If you find better solution please propose.

like image 444
Sasha Shpota Avatar asked Aug 03 '17 09:08

Sasha Shpota


2 Answers

You should be using onFocus event to handle the same as below,

<p-autoComplete [(ngModel)]="countries" 
                [suggestions]="filteredCountriesMultiple"                     
                (completeMethod)="filterCountryMultiple($event)" 
                styleClass="width12" (onFocus)="onFocus($event)">

  ....


onFocus(event){
      window.scrollTo(0, 0);

}

LIVE DEMO

like image 83
Aravind Avatar answered Oct 23 '22 10:10

Aravind


onUnselect(event: any) {
    // get index of the removed element
    // get total options count
    // get height of the element that contains the options
    // divide the height by number of options
    // set scroll potion to the result of division multiplied by the index
   document.querySelector('.ui-autocomplete-multiple-container.ui-inputtext').scrollTop = calculatedValue; 
}
like image 37
Lucky Soni Avatar answered Oct 23 '22 09:10

Lucky Soni