2013-04-10 65 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