2013-03-11 38 views
11

我創建了一個ajax搜索頁面,該頁面將包含一個搜索輸入框,一系列過濾器下拉菜單,然後是顯示結果的UL。由於過濾器的搜索部分將位於頁面上的一個獨立位置,因此我認爲創建一個處理協調輸入和ajax請求到搜索服務器端的服務是一個不錯的主意。然後可以由幾個單獨的控制器(一個用於搜索框和結果,另一個用於過濾器)調用。AngularJS - 使用服務作爲模型,ng-repeat不更新

我正在努力掙扎的主要事情是調用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,所以如果我在完全錯誤的方式去了解它,請告訴我這樣:)

回答

29

在您的HTML中,您需要引用在您的控制器的$ scope中定義的屬性。要做到這一點的方法之一是在您的控制器綁定$scope.searchService.resultssearchService.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

謝謝馬克。這是'angular.copy'部分,這是難題的一部分。 – 2013-03-12 09:40:38

+1

這對我來說是完全意義上的。我曾在3個其他服務/控制器上工作,但他們只是我推動的陣列,所以綁定從未打破。如果您完全替換陣列/對象,則需要使用副本!謝謝! – LukeP 2014-10-13 22:19:11

1

的問題是,你永遠更新您的範圍內的結果。有許多方法來做到這一點,但根據您當前的代碼,你可以先修改找到函數返回的結果:你的「公共的API」在

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

你使用一個模塊模式,使您searchService返回找到功能和結果一個數組,但你想使功能找到負責實際返回的結果。

設置,放在一邊,只要您撥打doSearch()在你的範圍,你要更新那些您searchService返回當前結果

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

我更新了的jsfiddle我的想法,不起作用,但我添加了一些委員和日誌來幫助您調試此問題。 http://jsfiddle.net/XTQSu/3/

+0

感謝您的努力。在這種情況下,我不希望'find'返回結果,因爲結果在一個控制器中是需要的,而find()可能是從另一個控制器調用的。這是將結果保存在本地服務中而不是在控制器中的原因。缺少的是將服務中的結果綁定到使用它們的控制器上。正如Mark指出的那樣,我沒有任何限制,所以這就是爲什麼它沒有更新。當我更新結果時,使用'angular.copy()'保持綁定完好無損。再次感謝您花時間回答。 – 2013-03-12 09:47:46