Nick
Nick

Reputation: 1831

How to show autocomplete drop-down when first clicking in text box?

I am using a Angular md-autocomplete which starts showing users the auto completion options in a drop-down after they first type in the text box. Is there anyway to have this dropdown shown when the user first clicks in the text box as well?

Here is the md-autocomplete html:

<md-autocomplete flex
                 role="combobox"
                 md-selected-item="text"
                 md-no-cache="true"
                 md-search-text="searchText"
                 md-search-text-change="searchTextChange(searchText)"
                 md-items="item in getMatches(searchText)"
                 md-item-text="item.autocompleteVal"
                 md-min-length="0"
                 md-selected-item-change="$parent.selectedItemChange(item)" on-enter ng-cloak>
                            <span id="autocompleteText" md-highlight-text="searchText" md-highlight-flags="^i">{{item.autocompleteVal}} </span>
</md-autocomplete>

Upvotes: 3

Views: 9886

Answers (5)

Anand Kadhi
Anand Kadhi

Reputation: 1878

Just add the following line

md-min-length="0"

This will trigger a md-items calls even when just clicked

Upvotes: 0

Emmad Zahid
Emmad Zahid

Reputation: 508

I was having same issue but setting the value of md-min-length to zero starts working

md-min-length="0"

Update: If it still does not work then make sure that the searchTerm is initially set to null

Controller

vm.searchTerm = null

Html:

md-search-text="vm.searchTerm"

Upvotes: 7

andreisrob
andreisrob

Reputation: 1715

As @Hodglem pointed out, the current Material docs use the valueChanges observable of the FormControl object to detect changes and filter the options to display on the autocomplete panel. They prime the initial value as "null" so that all the available options will display.

However, often your list of options comes from a service (as in my use case) and your list is empty when startsWith(null) runs, especially if this code is in the ngOnInit() method like it is in the Material docs. This method runs immediately, while the service takes time to fill the list.

Autocomplete is smart enough to not open the panel if there are no options, so the initial focus on the element will not open the panel since there are no options to display. Even after the list fills from the service, the filter only gets triggered with a change in value on the control, so until the user starts typing, autocomplete's list of options remains empty, and therefore the panel remains closed.

I have two solutions:

  1. Move the observable set up out of the ngOnInit() method, and into the subscribe() method that follows the call to the service that retrieves the options. After setting the list, run the observable set up. Now the panel will open on focus since the panel has options to display. (Make sure that the initialization of the FormControl remains in the ngOnInit() method, or the binding in the template will throw an error.)

  2. Scratch the observable approach, and bind the filter method to the control's native events, such as (focus) and (input). In the filter method, check if the passed-in value is null or empty, and if it is, return the entire list. This way, the filter gets triggered every time the user clicks on the control or changes its value, and as long as the user clicks on the control at least once after the service filled the list of options, the panel will display. Depending on your use case, I found that by the time the user moves the mouse and focuses on the control, the service already delivered the goods, and the panel opens.

Upvotes: 6

Hodglem
Hodglem

Reputation: 634

For Angular 2 and Material 2, setting startWith() on the valueChanges() observable of the control to null will show all of the values. Omitting this will result in the user first needing to type a value in to see results.

All values displayed on focus:

this.filterFuelTypeObservers.push(newFormGroup.controls.fuelType.valueChanges
    .startWith(null)
    .map(value => value ? this.fuelTypeFilter(value) : this.fuelTypes));

No values displayed until entry:

this.filterFuelTypeObservers.push(newFormGroup.controls.fuelType.valueChanges
    .map(value => value ? this.fuelTypeFilter(value) : this.fuelTypes));

I haven't, but I imagine you could play around with startWith() to set the on focus list to be filtered by something also.

Upvotes: 2

Valery Kozlov
Valery Kozlov

Reputation: 1577

Seems like demo from site works as you expected. https://material.angularjs.org/latest/demo/autocomplete

Upvotes: 2

Related Questions