如何使用$ resource填充Angular UI Bootstrap typeahead

时间:2013-04-10 14:26:54

标签: twitter-bootstrap asynchronous angularjs

我正在尝试使用我已设置的REST资源使用Angular UI bootstraps typeahead。但我不确定如何使用它的异步特性。

目前我已经调整了Angular UI Bootstrap给出的示例。

所以我的html看起来是这样的,调用getLibs()来获取typeahead下拉列表。

<div class='container-fluid' ng-controller="TypeaheadCtrl">
    <pre>Model: {{selected| json}}</pre>
    <input type="text"  typeahead="lib.name for lib in getLibs($viewValue)" active='active' ng-model="selected" typeahead-min-length='3' >
</div>

我的资源看起来像这样:

angular.module('LibraryLookupService', ['ngResource']).factory('Library', 
    function($resource){
        return $resource(   "../../api/seq/library/?name__icontains=:searchStr" , {} , 
        {   'get':    {method:'GET'},
            'query':  {method:'GET', params: {} ,  isArray:false },
        }
    )
}

);

我的控制器看起来像是这样(我猜它在这里我做错了什么):

function TypeaheadCtrl($scope , Library){

    $scope.selected = undefined;
    $scope.active = undefined ;

    $scope.libs = [{name:'initial'} , {name:"values"}];

    $scope.getLibs = function(viewValue){
        console.log("value:", viewValue);
        if (viewValue.length > 3 ) { 
            var return_vals =  Library.query({searchStr:viewValue},  function() {
                $scope.libs = return_vals.objects ; 
                console.log("here", $scope.libs) ; 
                }) ;
            }
        return $scope.libs
    }
}

据我所知,从getLibs()函数的返回值填充了typeahead菜单。 当调用getLibs()时,它正在查询REST接口,但最初返回一个空值。这是由提供给Library.query()方法的函数填充的,这是在从REST请求返回数据之后完成的。

这基本上意味着菜单正在按照我想要的一个按键更新。我输入'3456',它会在REST界面中填入'345'查询结果。

如何从Library.query()函数返回响应时更新菜单?我能正确地解决这个问题吗?

6 个答案:

答案 0 :(得分:7)

我这样解决了:

我的工厂:

angular.module('frontendApp')
  .factory('PersonService', function($resource) {
    // Service logic
    // ...

    return $resource(APP_CONFIG.prefixURLRest + '/person', {
      //id: '@id'
    }, {
      search: {
        method: 'POST',
        isArray: true
      }
    });

  });

我的控制器

...
$scope.searchTypeAhead = function(name) {
  var person = {
    'name': name
  };

  return PersonService.search(person)
    .$promise.then(function(response) {
      return response;
    });
};

答案 1 :(得分:6)

来自http://angular-ui.github.io/bootstrap/的typeahead指令继承promise API($q)以处理异步建议。 $resource的问题在于缺乏对promises的支持(最近才在unstable分支中添加)。所以你在这里有两个解决方案:

1)使用promises的$http中继(对于大多数自动完成的情况,IMO $ http应该足够了)。 2)切换到AngularJS的最新不稳定版本并使用promises。

$ resource的目的是使用完整的HTTP谓词集来定位RESTful端点。如果您只想查询数据,最好还是使用$ http来实现此目的。

有一个关于typeahead的类似问题,其答案涵盖了$http的使用情况:How to tie angular-ui's typeahead with a server via $http for server side optimization?

答案 2 :(得分:2)

如果您不想使用$ http(因为您想要重用现有的$资源),或者不想切换到不稳定的分支,则可以在promise中将对$ resource的调用包装起来。它有点冗长,但它确实有效。 快速示例(使用AngularJS 1.0.6):

$scope.getLibs = function(input){
    var defer = $q.defer();
    if (input){
        Library.query({searchStr:viewValue},
            function(data,headers){
                if (!$scope.$$phase){ //check if digest is not in progress
                    $rootScope.$apply(function(){
                        defer.resolve(data);
                    });
                } else {
                    defer.resolve(data);
                }
            },
            function(response){
                if (!$scope.$$phase){
                    $rootScope.$apply(function(){
                        defer.reject('Server rejected with status ' + response.status);
                    });
                } else {
                    defer.reject('Server rejected with status ' + response.status);
                }
            });
    } else {
        if (!$scope.$$phase){
            $rootScope.$apply(function(){
                defer.reject('No search query ');
                $log.info('No search query provided');
            });
        } else {
            defer.reject('No search query ');
            $log.info('No search query provided');
        }
    }
    return defer.promise;
};

答案 3 :(得分:2)

只需从资源中返回$ promise:

Utils

答案 4 :(得分:1)

如果您使用的是Angular 1.2.13(或其周围的某个地方,尚未对它们进行全部测试)

请参阅:https://stackoverflow.com/a/21888107/484802

为我工作。

答案 5 :(得分:1)

此代码适用于角度1.6和最新的ui的angular-bootstrap3-typeahead

GET / cities的

api端点响应?name =“somename”:

[
    {name: "somename", zipcode: 11111, etc: ""},
    {name: "somename", zipcode: 22222, etc: ""},
    {name: "somename", zipcode: 33333, etc: ""}
]

$资源工厂:

getCities: {
    url: '/cities',
    method: 'GET
}

<强>控制器:

$scope.getCities = function(name) {
    return City.getCity({
        name: name
    }).$promise.then(function(response) {
        return response;
    });
};

查看:

<input ng-model-control data-ng-model="city" uib-typeahead="city.name for city in getCities($viewValue)" />

此解决方案似乎不适用于过滤,请参阅https://github.com/angular-ui/bootstrap/issues/1740