2013-04-10 15 views
7

Próbuję uzyskać dostęp do bootstrapów Angular UI przy użyciu skonfigurowanego zasobu REST. Ale nie jestem pewien, jak sprawić, by działało z jego asynchroniczną naturą.

W tej chwili dostosowałem przykład podany przez Bootstrap Angular UI.

więc mój html wygląda tak, wywołując getLibs(), aby uzyskać listę dla listy rozwijanej 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> 

mój zasób wygląda tak:

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

);

mój kontroler wygląda tak (jestem zgadywania to tutaj robię coś niepoprawne):

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

Więc jak rozumiem, menu wpisywanie znaków z wyprzedzeniem jest wypełniany od wartości zwracanej z getLibs (). Wywołanie metody getLibs() powoduje wysłanie zapytania do interfejsu REST, ale początkowo zwracana jest pusta wartość. Jest on zapełniany przez funkcję dostarczaną do metody Library.query(), a odbywa się to po zwróceniu danych z żądania REST.

Oznacza to, że menu jest aktualizowane po jednym naciśnięciu klawisza później niż to, co chcę. Wpisuję "3456" i zapełnia się wyniki zapytania "345" do interfejsu REST.

Jak ustawić menu do aktualizacji po zwróceniu odpowiedzi z funkcji Library.query()? Czy poprawiam to poprawnie?

Odpowiedz

6

Dyspozytornia z interfejsem http://angular-ui.github.io/bootstrap/ przekaże interfejs API obietnicy ($q), aby obsłużyć asynchroniczne podpowiedzi. Problem z $resource polega na tym, że brakuje wsparcia dla obietnic (dodano go dopiero niedawno w gałęzi niestabilnej). Masz tutaj dwa rozwiązania:

1) przekaźnik na $http, który działa z obietnicami (IMO $ http powinno być więcej niż wystarczające dla większości przypadków automatycznego uzupełniania). 2) Przejdź do najnowszej niestabilnej wersji AngularJS i pracuj z obietnicami.

Celem zasobu $ jest praca z pełnym zestawem czasowników HTTP w celu kierowania na RESTful punkty końcowe. Jeśli chcesz po prostu zapytać o dane, możesz lepiej wykorzystać w tym celu $ http.

Jest podobne pytanie o wpisywanie znaków z wyprzedzeniem z odpowiedzią, która zakrywa jej użytkowania z $http: How to tie angular-ui's typeahead with a server via $http for server side optimization?

2

Jeśli nie chcesz używać $ http (bo chcesz ponownie wykorzystać istniejący zasób $), lub nie chcesz przełączać się do gałęzi niestabilnej, możesz zawrzeć połączenie do zasobu $ w obietnicę. Jest trochę gadatliwy, ale działa. Krótki przykład (przy użyciu 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

Rozwiązałem to w ten sposób:

Mój zakład:

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

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

    }); 

Mój kontroler

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

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

Właściwie można po prostu zwrócić obietnicę $ $ bez metody then(), ponieważ jest ona zbędna. – mameluc

+0

Nie rozumiem, dlaczego przekazujesz obiekt osoby podczas wywoływania usługi PersonService, ponieważ nie widzę obiektu Person w definicji fabryki. – peztherez

1

Wystarczy return $ obietnicę z zasobów:

UsuarioResource.query().$promise 
0

Kod ten jest pracuje dla kątowego 1.6 i najnowsze UI kątowe-bootstrap3-wpisywanie znaków z wyprzedzeniem

odpowiedź końcowy API dla GET/miast name = "somename":

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

$ fabryka zasobów:

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

kontroler :

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

widok:

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

Wydaje się, że to rozwiązanie nie działa z filtrowaniem, zobacz https://github.com/angular-ui/bootstrap/issues/1740.

Powiązane problemy