AngularJS - использование сервиса как модели, ng-repeat не обновляет
Я создаю страницу поиска ajax, которая будет состоять из окна ввода поиска, серии выпадающих списков фильтров, а затем UL, где отображаются результаты.
Поскольку часть фильтров поиска будет находиться в отдельном месте на странице, я подумал, что было бы неплохо создать службу, которая занимается согласованием входных данных и запросов ajax на стороне сервера поиска. Затем это можно вызвать несколькими отдельными контроллерами (один для поиска и результатов, а другой для фильтров).
Главное, с чем я борюсь, - это получить результаты для обновления при вызове ajax. Если я поместил ajax непосредственно в контроллер SearchCtrl, он будет работать нормально, но когда я перейду ajax в службу, он перестанет обновлять результаты при вызове метода find в службе.
Я уверен, что это что-то простое, что я пропустил, но, похоже, я не вижу его.
Разметка:
<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();
}]);
Вот грубый JSFiddle, я прокомментировал ajax, и я просто обновляю переменную результатов вручную в качестве примера. Для краткости я не включил выпадающие списки фильтров.
http://jsfiddle.net/XTQSu/1/
Я очень новичок в AngularJS, поэтому, если я пойду об этом совершенно не так, скажите мне так:)
Ответы
Ответ 1
В вашем HTML вам нужно ссылаться на свойство, определенное в вашем пространстве $control. Один из способов сделать это - привязать $scope.searchService.results
к searchService.results
один раз в вашем контроллере:
$scope.searchService.results = searchService.results;
Теперь эта строка будет работать:
<li data-ng-repeat="item in searchService.results">
В вашей службе используйте angular.copy()
вместо того, чтобы назначать новую ссылку на массив results
, в противном случае область вашего контроллера $потеряет привязку данных:
var new_results = [{ 'title': 'title 3' },
{ 'title': 'title 4' }];
angular.copy(new_results, results);
Fiddle. В скрипке я прокомментировал первоначальный вызов find(), поэтому вы можете увидеть, что обновление происходит, когда вы вводите что-то в поле поиска.
Ответ 2
Проблема заключается в том, что вы никогда не обновляете свои результаты в своей области. Существует много способов сделать это, но на основе вашего текущего кода вы можете сначала изменить функцию find, чтобы вернуть результаты:
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;
}
Вы используете шаблон модуля в своем "общедоступном API", поэтому ваш searchService возвращает функцию find и массив результатов, но вы хотите, чтобы функция find была ответственна за фактическое возвращение результатов.
Отметьте, что в любом случае, когда вы вызываете doSearch() в своей области, вам нужно обновить текущие результаты для тех, которые были возвращены вашей поисковой службой
$scope.doSearch = function(){
$scope.searchService.results = searchService.find($scope.search_term);
};
Я обновил ваш jsfiddle своими идеями, не работает, но добавил некоторые коммиты и журналы, чтобы помочь вам отладить эту проблему. http://jsfiddle.net/XTQSu/3/