我正在尝试使用我已设置的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()函数返回响应时更新菜单?我能正确地解决这个问题吗?
答案 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)
答案 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。