Bootstrap-UI Typeahead display more than one property in results list?
Asked Answered
J

1

26

I'm using ui-bootstrap typeahead. It works brilliantly! However, I'm wondering if its possible to display multiple properties or even HTML in the results list. Typical problem: the search returns more than one object with the same value. Eg search for 'amazing grace' return ['amazing grace', 'amazing grace'] where one is the movie and one is the song. I would like the results list to be more like:

amazing grace | movie
amazing grace | song

... so the user knows exactly what they're selecting. Even better would be an icon next to the title. In other words, each result in the list contains some HTML. Can either of these be done out of the box?

Jenkins answered 15/8, 2013 at 3:20 Comment(2)
https://mcmap.net/q/535401/-how-do-you-iterate-over-an-array-of-objects-for-typeahead, and take a look at this demo jsfiddle.net/ZKqQM/9Jedidiah
@sza thanks for the tip. I never would have found that question given its title and that I already know about object iteration within typeahead, just not how to display it. CheersJenkins
R
100

The thing to ntice about the typeahead directive from http://angular-ui.github.io/bootstrap/ is that tries to mimic syntax used by the select directive from AngularJS. It means that all the expressions used to select a model to bind and a label are AngularJS expressions. This in turns means that you can use whatever AngularJS expression to calculate the text of your label.

For example, to display your desired text you could write:

typeahead="item as item.title + ' (' + item.type + ')' for item in titles | filter:{title:$viewValue}"

Provided that your data model looks like follows:

$scope.titles = [
    {title: 'Amazing Grace', type: 'movie'},
    {title: 'Amazing Grace', type: 'song'}
  ];

Working plunk here: http://plnkr.co/edit/VemNkVnVtnaRYaRVk5rX?p=preview

Writing complex expressions for a label in the typeahead attribute might get ugly but nothing stops you from moving label calculation logic to a function exposed on a scope, ex.:

typeahead="item as label(item) for item in titles | filter:{title:$viewValue}"

where the label is a function exposed on a scope:

$scope.label = function(item) {
    return item.title + ' (' + item.type + ')';
  };

Another plunk: http://plnkr.co/edit/ftKZ96UrVfyIg6Enp7Cy?p=preview

As far as your question regarding icons go - you could embed HTML in the label expressions but this gets awful to write and maintain. Fortunately the typeahead directive allows you to provide a custom template for your matched item, like so:

typeahead-template-url="itemTpl.html"

In the custom template you can use any expressions or AngularJS directive you would like. Adding icons becomes trivial with a little help from the ngClass directive:

<script type="text/ng-template" id="itemTpl.html">
   <a tabindex="-1">
      <i ng-class="'icon-'+match.model.type"></i>
      <span  ng-bind-html-unsafe="match.model.title | typeaheadHighlight:query"></span>
   </a>
</script>

And the working plunk: http://plnkr.co/edit/me20JzvukYbK0WGy6fn4?p=preview

Pretty neat little directive, isn't it?

Rundgren answered 15/8, 2013 at 11:14 Comment(8)
Very neat! You wrote it didn't you?? ;) For some reason though, I've had a hard time finding good docs for it. It would be nice if there was a link to the docs with all the options etc from this page angular-ui.github.io/bootstrap/#/typeaheadJenkins
How would you go about calling a controller function from a link embedded in the template? The function is never called so it seems that we are in a different scope then? For a detailed explanation see: #18442428Organist
THANK YOU SO MUCH for the sample & Plunkr. I've been battling with typeahead in a ng-grid for 2 days now, and your example helped me grok things.Alejandro
Should you have any problems (e.g. empty popup) try using bind-html-unsafe instead of ng-bind-html-unsafe. (That worked for me - I'm using UI.bootstrap.typehead for boostrap3 (boostrap3 branch)Folkways
Template is great, but how to make it access scope parameters? Please see my question at http://stackoverflow.com/questions/24833151/how-to-make-bootstrap-typeahead-template-to-use-scope-parameter-in-angular for details.Tutto
The second plunkr is the same as the first plunkr you provided.Cotidal
Is it always "match.model.foo"? I'm trying to use match.model | json to check what's in there and getting an unrecognized expression error. How can I debug?Aquavit
I have tried your plunkr. It works very well with angular 1.05 but not with angular 1.2.2. Why???Fortunna

© 2022 - 2024 — McMap. All rights reserved.