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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15928644/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 16:52:57  来源:igfitidea点击:

How to use a $resource to populate Angular UI Bootstrap typeahead

twitter-bootstrapasynchronousangularjs

提问by wobbily_col

I am trying to get Angular UI bootstraps typeahead working with a REST resource I have set up. But I am not sure how to get it working with it's asynchronous nature.

我正在尝试让 Angular UI 引导程序提前输入我设置的 REST 资源。但我不确定如何让它与它的异步性质一起工作。

At the moment I have adapted the example given by Angular UI Bootstrap.

目前我已经改编了 Angular UI Bootstrap 给出的例子。

so my html looks like so, calling getLibs() to get the list for the typeahead dropdown.

所以我的 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>

my resource looks like so:

我的资源看起来像这样:

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 },
        }
    )
}

);

);

my controller looks like so (I am guessing it is here I am doing something incorrect):

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

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
    }
}

So as I understand it, the typeahead menu is being populated from the return value of the getLibs() function. When getLibs() is called it is querying the REST interface, but initially an empty value is returned. This is being populated by the function supplied to the Library.query() method, and this is done after the data is returned from the REST request.

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

This means basically that the menu is being updated one keypress later than what I want. I type '3456' and it gets populated with results of a '345' query to the REST interface.

这基本上意味着菜单的更新比我想要的晚一键。我输入“3456”,它会填充“345”查询到 REST 接口的结果。

How do I get the menu to update when the response is returned from the Library.query() function? Am I going about this correctly?

当从 Library.query() 函数返回响应时,如何让菜单更新?我这样做正确吗?

采纳答案by pkozlowski.opensource

The typeahead directive from http://angular-ui.github.io/bootstrap/relays on the promise API ($q) to handle asynchronous suggestions. The trouble with $resourceis that is used to lack support for promises (it was added only recently in the unstable branch). So you've got 2 solutions here:

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

1) relay on $httpthat works with promises (IMO $http should be more than enough for most auto-complete cases). 2) Switch to the latest unstable version of AngularJS and work with promises.

1) 中继$http与承诺一起工作(对于大多数自动完成情况,IMO $http 应该绰绰有余)。2) 切换到最新的 AngularJS 不稳定版本并使用 promise。

The purpose of the $resource is to work with the full set of HTTP verbs to target RESTful endpoints. If you want to just query data you might be better off using $http for this purpose anyway.

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

There is a similar question about typeahead with an answer that covers of its usage with $http: How to tie angular-ui's typeahead with a server via $http for server side optimization?

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

回答by Joander Vieira Candido

I solved it this way:

我是这样解决的:

My factory:

我的工厂:

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

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

  });

My controller

我的控制器

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

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

回答by sgdesmet

If you don't want to use $http (because you want to reuse your existing $resource), or don't want to switch to the unstable branch, you can wrap the call to your $resource in a promise. It's a bit verbose, but it works. Quick example (using AngularJS 1.0.6):

如果你不想使用 $http(因为你想重用你现有的 $resource),或者不想切换到不稳定的分支,你可以把对你的 $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;
};

回答by Rafael Coutinho

Just return $promise from resource:

只需从资源中返回 $promise :

UsuarioResource.query().$promise

回答by joe.js

This code is working for angular 1.6 and latest ui's angular-bootstrap3-typeahead

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

api endpoint response for GET /cities?name="somename":

GET /cities?name="somename" 的 api 端点响应:

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

$resource factory:

$资源工厂:

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

controller:

控制器:

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

view:

看法:

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

It seems that this solution doesn't work with filtering, see https://github.com/angular-ui/bootstrap/issues/1740.

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

回答by Andrew Lank

If you are on Angular 1.2.13 (or somewhere around there, haven't tested them all)

如果您使用的是 Angular 1.2.13(或附近的某个地方,还没有全部测试过)

See: https://stackoverflow.com/a/21888107/484802

参见:https: //stackoverflow.com/a/21888107/484802

Worked for me.

对我来说有效。