2013-03-11 9 views
11

Tworzę stronę wyszukiwania ajax, która będzie składać się z pola wyszukiwania, szeregu list rozwijanych filtrów, a następnie UL, gdzie wyświetlane są wyniki.AngularJS - Używanie usługi jako modelu, ng-repeat nie aktualizowanie

Ponieważ część filtrów wyszukiwania będzie znajdować się w osobnym miejscu na stronie, pomyślałem, że dobrze byłoby utworzyć usługę, która zajmuje się koordynacją danych wejściowych i żądaniami ajaxów po stronie serwera wyszukiwania. Może to zostać wywołane przez kilka oddzielnych Kontrolerów (jeden dla pola wyszukiwania i wyników, a drugi dla filtrów).

Najważniejszą rzeczą, z którą walczę, jest uzyskanie wyników do odświeżenia, gdy wywoływany jest ajax. Jeśli umieściłem ajax bezpośrednio w kontrolerze SearchCtrl, działa dobrze, ale kiedy przeniesię ajax do usługi, przestaje on aktualizować wyniki, gdy wywoływana jest metoda wyszukiwania w usłudze.

Jestem pewien, że jest to coś prostego, za czym tęskniłem, ale nie mogę tego zobaczyć.

Markup:

<div ng-app="jobs"> 
    <div data-ng-controller="SearchCtrl"> 
     <div class="search"> 
      <h2>Search</h2> 
      <div class="box"><input type="text" id="search" maxlength="75" data-ng-model="search_term" data-ng-change="doSearch()" placeholder="Type to start your search..." /></div> 
     </div> 
     <div class="search-summary"> 
      <p><span class="field">You searched for:</span> {{ search_term }}</p> 
     </div> 
     <div class="results"> 
      <ul> 
       <li data-ng-repeat="item in searchService.results"> 
        <h3>{{ item.title }}</h3> 
       </li> 
      </ul> 
     </div> 
    </div> 
</div> 

angularjs:

var app = angular.module('jobs', []); 

app.factory('searchService', function($http) { 
    var results = []; 

    function find(term) { 
     $http.get('/json/search').success(function(data) { 
      results = data.results; 
     }); 
    } 

    //public API 
    return { 
      results: results, 
      find: find 
    }; 
}); 

app.controller("SearchCtrl", ['$scope', '$http', 'searchService', function($scope, $http, searchService) { 
    $scope.search_term = ''; 
    $scope.searchService = searchService; 

    $scope.doSearch = function(){ 
     $scope.searchService.find($scope.search_term); 
    }; 

    $scope.searchService.find(); 
}]); 

Tutaj jest szorstka JSFiddle, mam wykomentowane Ajax, a ja po prostu aktualizowania zmienną wyników ręcznie jako przykład. Dla zwięzłości nie uwzględniłem menu rozwijanego filtru.

http://jsfiddle.net/XTQSu/1/

Jestem bardzo nowy angularjs, więc jeśli mam o nim w sumie przez niewłaściwy sposób, proszę mi powiedzieć, tak :)

Odpowiedz

29

W kodzie HTML należy odwołać się do właściwości zdefiniowanej w zakresie $ kontrolera kontrolera.Jednym ze sposobów na to jest do wiązania $scope.searchService.results do searchService.results raz w kontrolerze:

$scope.searchService.results = searchService.results; 

Teraz ta linia będzie działać:

<li data-ng-repeat="item in searchService.results"> 

w usłudze, należy angular.copy() zamiast przypisywania nowy odnośnik tablicę results, inaczej $ zakres kontroler będzie utracić dane wiążące:

var new_results = [{ 'title': 'title 3' }, 
        { 'title': 'title 4' }]; 
angular.copy(new_results, results); 

Fiddle. W skrzypcach skomentowałem początkowe wywołanie funkcji find(), aby można było zobaczyć aktualizację po wpisaniu czegoś w polu wyszukiwania.

+2

Dzięki Mark. Była to część "kątowa.kopia", która była brakującym elementem układanki. –

+1

To ma teraz dla mnie sens. Miałem to działające na 3 innych usługach/kontrolerach, ale były to tylko tablice, które naciskałem, aby wiązanie nigdy się nie zepsuło. Jeśli całkowicie wymieniasz tablicę/obiekt, musisz użyć kopii! Dzięki! – LukeP

1

Problem polega na tym, że nigdy nie aktualizujesz Twoje wyniki w twoim zasięgu. Istnieje wiele sposobów, aby to zrobić, ale na podstawie aktualnego kodu, można najpierw zmodyfikować znaleźć funkcja zwraca wyniki:

function find(term) { 
    $http.get('/json/search').success(function(data) { 
      var results = data.results; 

    }); 
    //also notice that you're not using the variable 'term' 
    //to perform a query in your webservice 
    return results; 
} 

używasz wzór modułu API w „publicznej”, tak Twój Zlecenie wyszukiwania zwraca znaleźć funkcję i tablicę wyników, ale chciałby, aby funkcja znaleźć być odpowiedzialny za rzeczywiście powrocie wyniki.

Ustawienie to na bok, gdy dzwonisz doSearch() w swoim zakresie, którą chcesz zaktualizować aktualnych wyników dla zwracanych przez Zlecenie wyszukiwania

$scope.doSearch = function(){ 
    $scope.searchService.results = searchService.find($scope.search_term); 
}; 

zaktualizowałem swoją jsfiddle z moje pomysły, nie są funkcjonalne, ale dodałem trochę prowadnic i dzienników, aby pomóc ci w debugowaniu tego problemu. http://jsfiddle.net/XTQSu/3/

+0

Dzięki za twoje wysiłki. W tym przypadku nie chciałem, aby 'find' zwracało wyniki, ponieważ wyniki są potrzebne w jednym kontrolerze, podczas gdy' find() 'może być wywołany z innego kontrolera. To był powód, dla którego wyniki były lokalne dla usługi, a nie dla kontrolera. Brakowało powiązania wyników w usłudze z kontrolerem, w którym są używane. Jak zaznaczył Mark, nie miałem żadnego odniesienia, dlatego nie aktualizowałem. Użycie 'angular.copy()' zachowało wiązanie w stanie nienaruszonym po zaktualizowaniu wyników. Jeszcze raz dziękuję za poświęcenie czasu na odpowiedź. –

Powiązane problemy