Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
230 views
in Technique[技术] by (71.8m points)

javascript - AngularUI-Bootstrap Typeahead: Grouping results

I am implementing typeahead using AngularUI-Bootstrap. I need to show the results grouped based on some values coming from the database. Here's a sample scenario

  1. There are some users in the database, each user has a "Department". One user name can be available in multiple departments.
  2. The end-user types in the names to search users from the database and retrieves the list in the typeahead list. Since one user name can belong to multiple departments, the requirement is to show the user names grouped by different departments. Something like this: enter image description here
  3. Then the user can select the desired user name and proceed.

As per the Typeahead documentation present here, I don't see any option to cater to my requirement.

I have tried the this workaround: Whenever the typeahead array is getting formed, I appended the user department to the array element:

$scope.fetchUsers = function(val) {
        console.log("Entered fetchUsers function");
        return $http.get("http://localhost:8080/TestWeb/users", {
            params : {
                username : val
            }
        }).then(function(res) {
            console.log("Response:",res);
            var users = [];
            angular.forEach(res.data, function(item) {
                users.push(item.UserName + " - " + item.UserDepartment);
            });
            console.log("users=",users);
            return users;
        });
    };

This way, at least the end user sees the department. But when I select the record, the selected value is the full content of the array element. Below is sample screenshot to elaborate:

HTML

Users from local service
<pre>Model: {{userList | json}}</pre>
<input type="text" ng-model="userList" placeholder="Users loaded from local database" 
typeahead="username for username in fetchUsers($viewValue)" 
typeahead-loading="loadingUsers" class="form-control">
<i ng-show="loadingUsers" class="glyphicon glyphicon-refresh"></i>

User types in the string

Search result

User selects one record

user selects one record

I want to avoid the department (in this case, string - Desc 4 ) when user selects a record.

Is there any way I can achieve this grouping without any workaround? Or is there any way I can enhance my workaround?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I used to have a similar requirement and here is how I did it that time.

Example Plunker: http://plnkr.co/edit/zujdouvB4bz7tFX8HaNu?p=preview

The trick is to set the typeahead-template-url to a custom item template:

<input type="text" class="form-control" placeholder="Users loaded from local database"
    ng-model="selectedUser"
    typeahead="user as user.name for user in getUsers($viewValue)"
    typeahead-template-url="typeahead-item.html" />

The item template, this represent each item in a dropdown:

<div class="typeahead-group-header" ng-if="match.model.firstInGroup">Desc {{match.model.group}}</div>
<a>
  <span ng-bind-html="match.label | typeaheadHighlight:query"></span>
</a>

As you can see, there is an ng-if to show a group header if that item has a property firstInGroup set to true.

The firstInGroup properties are populated like this using lodashjs:

$scope.getUsers = function (search) {
  var filtered = filterFilter(users, search);

  var results = _(filtered)
    .groupBy('group')
    .map(function (g) {
      g[0].firstInGroup = true; // the first item in each group
      return g;
    })
    .flatten()
    .value();

  return results;
}

Hope this fit to your requirement too.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...