Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Notification on Selection for Typeahead #433

Closed
nwpappas opened this issue May 13, 2013 · 23 comments
Closed

Notification on Selection for Typeahead #433

nwpappas opened this issue May 13, 2013 · 23 comments

Comments

@nwpappas
Copy link

Implement event notification for user selection of typeahead, so developer can capture selection and perform additional additional actions.

The AngularStrap project's typeahead, a wrapper for Bootstrap (vs. native AngularJS), fires a common event for all typeahead fields.

Example:

  1. User enters an Employee ID.
    • Typeahead information gathered from $http request as field is filled.
  2. User selects Employee ID from typeahead list, either by click or key stroke.
  3. updater makes $http request for complete employee record and fills in remaining form elements.
  4. User reviews fields and can update (e.g., update "Richard" to "Bob" in name field - or - job title is incorrect).

Additionally, typeahead is hooked up to name field so user can type in name instead of Employee ID. Same process as above follows.

As a result, it would be very beneficial if each typeahead had its own updater callback instead of a single common event fired when any typeahead is updated. Multiple typeaheads could exist on the same page.

Below is a jQuery implementation of the concept:

HTML:

<input type="text" pattern="[0-9]*" class="span6" id="textbox_EMPID" data-provide="typeahead" placeholder="8675309">

JavaScript:

$('#textbox_EMPID').typeahead({
  minLength: 3,
  source: function (query, process) 
  {
    $.get(
      '/visitorLog/search',
      { b : query },
      function(data)
      {
        process(data);
      },
      "json"
    );
  },
  updater: function (item)
  {
    $.get(
      '/visitorLog/search',
      { b : item, emp : true },
      function(data) 
      {
        jQuery.parseJSON(data).forEach(function(element, index, array) 
        {
          // fills out the remaining form fields based on employee id search
          autoFieldComplete(element);
        });
      },
      "json"
    );

    return item;
  },
/*
  matcher: function (item) {
  },
  sorter: function (item) {
  },
  highlighter: function (item) {
  },
*/
});

Typeahead selection event could return the selected value or the selection object. If selected object can be returned it opens up ability to query database only once, pulling a complete record with a single typeahead selection.

Basic extension of use case:

  • Manufacturing Parts Search. On selection of part number from typeahead, the complete part record is queried and displayed.
  • Subcategory Selection. The selection made in a "category" field determines what typeahead options are available in "subcategory" section, which would have to be retrieved after the initial selection (similar to an "editable combobox", allowing user to select existing or enter new value).

The notion is simply that an value from a typeahead field could one piece of a larger record, which could by queried on if the developer has access to the updater (to use Twitter Bootstrap terminology) event.

@pkozlowski-opensource
Copy link
Member

@EvilClosetMonkey I'm looking into this one right now. I perfectly understand your use-case now but I think that we shouldn't be directly translating jQuery concepts to the AngularJS world. With AngularJS we are relaying to 2-way data binding a lot, especially in input fields. Here I'm getting an impression that you want to mix searching for records and editing records.

Let's say I do a form for searching / editing part numbers. If I've got only one form with multiple filelds where typeaheads are bound to the id and name fields, you would be using the same form for retrieving and editing data. IMO it is confusing and would potentially result in bizzare situations. How would you manage the name fileld - how would you distinguish a situation where user is searching for results vs. editing a name?

IMHO the better solution here would be have a separate search field where users can type either a part number or its name. Typeahead would allow you to retrieve the whole record and use it to data-bind other fields.

Having said all the above I'm not trying to force you to change your UI or your flow. As I've said implementing selection callback would be trivial but I want to make sure that new code is added only when needed. We want to keep this library concise and focused and as such I want to make sure that I understand use-cases before adding new code.

Would be great if we could collaborate on this one to get to the best solution.

@nwpappas
Copy link
Author

@pkozlowski-opensource, I agree that id and name example was not the best. The "Subcategory Selection" use case is a little better one. The basic notion being that multiple typeaheads can be present on a single page and having a hook as to which typeahead an event came from is very useful.

@ecolman
Copy link

ecolman commented May 30, 2013

I'm needing this exact functionality as well, an event that fires when the user selects something from the typeahead.

@EvilClosetMonkey I agree with your notion of having an event return with a hook to determine which typeahead (or model). I'm already encountering this use-case of multiple typeaheads on a single page...

@pkozlowski-opensource
Copy link
Member

@ecolman-ap @EvilClosetMonkey sorry, I kind of forgotten about this one... You will have to bear with me, as I'm still puzzled about the exact use-case. As I was saying already events on selection would be trivial to implement... but I'm failing to see why we would need them with data-binding!

Could we make this discussion less abstract by focusing on a real use-case? Could one of you guys setup a plunker that exposes a problem / use-case you are trying to tackle?

Once again, I want this typeahead to be the best autocomplete widget on earth but I don't want to add code for nothing...

@ajoslin
Copy link
Contributor

ajoslin commented May 30, 2013

..Also, doesn't ng-change work since we're using an ng-model?

@ecolman
Copy link

ecolman commented May 30, 2013

I'm using typeahead for a search and I'd like to know the difference between a user initiated search (they click a button), a typeahead item selection and just typing into the input.

These events would need to be handled differently:

  • Initiate search on click of button or typeahead selection
  • Do nothing on normal typing

There is no way to differentiate between typing in the input and a selection from the typeahead. I suppose you could map a GUID to each item and try to parse the GUID each time in the ng-change function...

Here is a plnkr use-case:
I want to submit a search on either selection of a typeahead value or clicking of button
http://plnkr.co/edit/NA841u?p=preview

@nwpappas
Copy link
Author

No, ng-change does not work. Setting up an ng-change on the input field will cause the callback to fire as the user types out the contents "ACME Cor" (on their way to "ACME Corporation"), if the same input field is being used for entry & display. This issue is to request that a callback be available when the user selects "ACME Corporation" from the typeahead, in the same way the Bootstrap updater callback works.

For example -- if the callback is querying a database, you would not want to fire off a new $http each time another letter is typed in; instead only sending off the query when you know exactly what to look for per a user action (i.e., "ACME Corporation" upon selection from the typeahead). The reply from that $http request resulting in additional details about the "ACME Corporation".

Alternatively, the user may type in "Encom Corporation" which is not a typeahead option. This is still may be a valid entry (i.e., the user does not have to enter an existing value), but a $http request is not required because we already know it isn't in the database to query additional information for.

I will work on a Plunkr when I have a chance. Not hard to make one up, just need the free time to do it.

@johnobe
Copy link

johnobe commented Jun 1, 2013

I'm using the typeahead for tagging.

When the user selects an item from the typeahead I would like to push the tag object onto an array of selected tags and clear the input.

Here's my plnkr use case: http://plnkr.co/edit/j0org6wwen7Qzew57NrK?p=preview

@jamarparris
Copy link

The example provided by @johnobe is my exact use case.

@pkozlowski-opensource
Copy link
Member

@johnobe @jamarparris @EvilClosetMonkey OK, I'm convinced :-) Will push a fix somewhere next week. Feel free to open a PR if you want it faster - should be really easy one.

@jamarparris
Copy link

Awesome. Right now I pass to typeahead an array of objects (and then access the name using dot notation) so it'd be great if it returned the full object that was selected so that I can access other attributes such as id, etc.

@pkozlowski-opensource
Copy link
Member

@jamarparris yes, in fact the only thing we need to decide upon is the exact syntax and params passed to this selection callback. I can see 2 main options:

<input ... typeahead-on-select='selectCallback'>

where the selectCallback needs to be defined on scope and would take the following params:

  • full object (taking typeahead="state as state.name for state in states | filter:$viewValue"" as an example it would be state)
  • $viewValue

OR (I think I like this one better):

<input ... typeahead-on-select='selectCallback'($modelValue, $viewValue)>

Of course the list of arguments could be extended (adding label, for example).

What do you guys think?

@jamarparris
Copy link

I do like the second option as like you say, you could add additional arguments which could be handy.

@nwpappas
Copy link
Author

nwpappas commented Jun 3, 2013

I like the extensible nature of the 2nd option, but I've never seen an AngularJS callback work in the way illustrated in the 2nd option. Admittedly I'm still pretty new the framework and the power behind it. Is that method something supported elsewhere in the framework?

@pkozlowski-opensource
Copy link
Member

@EvilClosetMonkey AngularJS core is full of examples that work like option (2). For example you can pass an optional $event argument to the click handler: http://docs.angularjs.org/api/ng.directive:ngClick

@johnobe
Copy link

johnobe commented Jun 5, 2013

@pkozlowski-opensource Excellent News!

I agree with the others that option (2) provides a bit more flexibility.

@ecolman
Copy link

ecolman commented Jun 5, 2013

@pkozlowski-opensource I like option 2 for the flexibility, but it isn't pretty. Can we keep the arguments optional and be able to use option 1 unless otherwise needed?

@brancusi
Copy link

brancusi commented Jun 7, 2013

Would a notification when "no matches" are found be something to consider while we're at it?

I am creating a quick entry form, and need a way to detect when the user is entering an item not part of the data set.

At that point it would prompt them somehow to create a new entry with that value.

Any suggestions?

@nwpappas
Copy link
Author

nwpappas commented Jun 8, 2013

@brancusi You would need an additional action to know the user is done typing. On that action you could use existing mechanisms to do a check and add the new entry if necessary.

@pkozlowski-opensource
Copy link
Member

Just landed a fix for this via 91ac17c.

Check this unit test for the usage scenario:

it('should invoke select callback on select', function () {

@JobaDiniz
Copy link

I know this is a very old issue, but the following code isn't working:

<input type="text" id="search-input" class="form-control" ng-model="term" typeahead="content for content in executeQuery($viewValue)" typeahead-on-select="onSelect($item, $model, $label, $viewValue)" typeahead-input-formatter="format($model)" typeahead-template-url="mainModule/templates/topSearch.html" typeahead-wait-ms="100" />
$scope.onSelect = function ($item, $model, $label, $viewValue) {

$viewValue is undefined, why?

@hectormateos
Copy link

I'm in the same problem. typeahead-on-select not works

<--input type="text" class="form-control input-lg regularText" ng-model="searchInputText" typeahead="prediction.name for prediction in getFinderPredictionList($viewValue)" typeahead-min-length="3" typeahead-wait-ms="500" typeahead-template-url="searchResultItemDropDownTemplate" typeahead-on-select="trackResultClick($item)">

<--script type="text/ng-template" id="searchResultItemDropDownTemplate">




</script>

$scope.trackResultClick = function(item) {
alert(2);
//do something
};

@murraybauer
Copy link

typeahead-on-select does work @hectormateosoblanca. This worked for me.
http://stackoverflow.com/questions/16109364/angular-ui-bootstrap-typeahead-callback-on-selectmatch/17994624#17994624

@JobaDiniz $viewValue does not exist in the spec. See:

it('should invoke select callback on select', function () {

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests