-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Typeahed: allow search on focus #698
Comments
Another problem to solve is that the usual |
Good point! We could un-subscribe on |
This is blocked on #723 |
It could be really useful. |
So is it possible to implement or this is just a suggestion? Sorry for my dumb doubt, i'm trying to understand github yet |
I have a workaround for this for people who want this functionality now. On the input element that has typeahead add a focus handler:
In the focus handler trigger an input event:
It would be nice to not have to do this, but it works for now. |
When will this issue be fixed? |
@beaverusiv, that works thanks! |
I have created a gist with the entire typeahead wrapper I have: https://gist.github.com/beaverusiv/2d5818567b24bee200f5b4d6c333371c Do with it as you please, but I will not provide support or answer questions about it. I believe @scotschroeder you will be interested mainly in |
Hi guys, Thanks |
Hello, I worked on the issue to try figuring out solutions, ideas, and here they are. The feature requirementsAs seen by the end user:
Additional requirements as seen by the application developer:
An example of a scenario that should be possible with such a feature
The last point illustrates that it is important to know whether the current search request comes from an Possible implementationsNothingOn the application side, it is already possible to add a Example usage: import {Component} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject'; // ★
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/merge'; // ★
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
@Component({
selector: 'app-root',
template: `
<form>
<input
name='input'
[(ngModel)]='searchTerm'
[ngbTypeahead]='search'
(focus)='handleFocus()' <!-- ★ -->
type='text'
/>
</form>
`
})
export class AppComponent {
public searchTerm: string;
private focus$ = new Subject<null>(); // ★
handleFocus() {
this.focus$.next(null); // ★
}
search = (input$: Observable<string>): Observable<any> => {
return input$
.debounceTime(200)
.distinctUntilChanged()
.merge(this.focus$) // ★
.map(searchTerm => ...);
}
} Pros:
Cons:
Create ourselves an observable from the focus event and give it to the userExample usage: import {Component} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/merge'; // ★
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
@Component({
selector: 'app-root',
template: `
<form>
<input
name='input'
[(ngModel)]='searchTerm'
[ngbTypeahead]='search'
type='text'
/>
</form>
`
})
export class AppComponent {
public searchTerm: string;
search = (input$: Observable<string>, /* ★ */ focus$: Observable<string>): Observable<any> => {
return input$
.debounceTime(200)
.distinctUntilChanged()
.merge(focus$) // ★
.map(searchTerm => ...);
}
} Pros:
Cons: I don't see any. However it would require more API design, since I don't think we should extend the arguments list too much for any possible event. Also, we could optimize the implementation by providing an option so that if the feature is not wanted there is no new event handler added and no corresponding observable created. Merge ourselves the focus observable with the input observableThere are two fashions for this one: backward compatible and non-backward compatible. Backward compatibleExample usage: //...
export class AppComponent {
public searchTerm: string;
search = (input$: Observable<string>): Observable<any> => {
return input$
.debounceTime(200)
.distinctUntilChanged()
.map(searchTerm => ...);
}
} Pros:
Cons:
Non backward compatibleExample usage: //...
export class AppComponent {
public searchTerm: string;
search = (input$: Observable<{from, value}> /* ★ */): Observable<any> => {
return input$
.debounceTime(200)
.distinctUntilChanged()
.map(payload => {
const {from, value} = payload; // ★
if (from === 'focus') {
// ...
} else {
// ...
}
});
}
} Pros:
Cons:
ConclusionI personally prefer the second option for these reasons:
I will leave this pending for comments for some days, and if no decision stands out we will make one and implement it. PS: this whole feature based on focus events requires a very small and simple fix inside the TypeAhead to avoid trying to write an |
I like the "Create ourselves an observable from the focus event and give it to the user" solution, I feel it gives the greatest flexibility for users and backward compatibility which to me is important to help keep libraries up to date and decoupled from when I may want to change the UX surrounding a component. |
A few issues to be fixed for the implementation to workI mentioned at the end of my previous comment that the implementation would require a small fix to be done regarding the management of the internal user input. This is not the only one, and the following I'm going to describe is due to the same problem: the The problem comes from the fact that the latter property is changed only with With the feature we want to implement, imagine the following scenario:
This feature implementation would also require #1853 to be fixed to handle the case where the focus occurs because of a click in the input. Without it, the focus event would be received first and dropdown opened, and then the click event would be received and dropdown closed, making it impossible to open the dropdown immediately in this use case. Introducing a small delay for opening works but is not necessarily what we want. |
Take care that the hack of @beaverusiv can introduce another problems.
Scenario :
This is very inconvenient to lost value just by giving focus to field without entering some text. And I do not see hack to eventually restore value corresponding to entered text when focus is lost. Any idea ? So for future implemntation, we should be careful that value is not unset when field receives focus and dropdown is opened,while user enters no text. May be a simple solution could be to provide a public |
In certain use-cases one might want to trigger typeahead search when the input field gets focused. You can see a good example of this on https://www.kayak.fr/flights
It should be trivial to implement this on our side since we should simply listen to the
focus
event, get whatever value we've got in the input and push it down the observable stream. The only tricky part might be taking into account the situation where a given input field hasautofocus
attribute (in this case we shouldn't kick off things).There should be a flag for this option (I guess false by default).
I'm going to mark this as
medium
difficulty and I think that it is a good issue for ambitious community members. As always test are essentials.The text was updated successfully, but these errors were encountered: