2013-04-10 66 views
7

我正在尝试使用我设置的REST资源来获取Angular UI引导程序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的返回值填充( )功能。 当调用getLibs()时,它正在查询REST接口,但最初会返回一个空值。这是由提供给Library.query()方法的函数填充的,并且这是在从REST请求返回数据之后完成的。

这意味着基本上菜单正在更新一个按键晚于我想要的。我键入'3456',并将其结果填充到REST接口的'345'查询结果。

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

回答

6

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

1)继承$http与承诺(国际海事组织$ http应该是绰绰有余的大多数自动完成的情况下)。 2)切换到最新的不稳定版本的AngularJS并使用promise。

$资源的用途是使用全套HTTP动词来定位RESTful端点。如果你只想查询数据,那么无论如何你都可以使用$ http来达到这个目的。

有关于与$http其使用的覆盖答案预输入一个类似的问题:How to tie angular-ui's typeahead with a server via $http for server side optimization?

2

如果你不想使用$ HTTP(因为你想重用现有资源$),或不想切换到不稳定的分支,您可以将呼叫包装到您的$资源中。这有点冗长,但它有效。 简单的例子(使用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; 
}; 
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; 
    }); 
}; 
+7

实际上,如果没有使用then()方法,您可以返回$ promise,因为它是多余的。 – mameluc 2015-05-12 09:13:02

+0

我不明白你为什么在调用PersonService时传递person对象,因为我在工厂定义中看不到Person对象。 – peztherez 2015-12-05 16:08:20

1

刚刚从资源返回$承诺:

UsuarioResource.query().$promise 
0

此代码是为角1.6工作和最新的UI的角bootstrap3-预输入

为GET /城市名称= “somename” API端点回应:

[ 
    {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