2013-03-11 4 views
11

検索入力ボックス、一連のフィルタドロップダウン、結果が表示されるULで構成されるajax検索ページを作成しています。AngularJS - サービスをモデルとして使用すると、ng-repeatが更新されない

検索のフィルタ部分がページ上の別の場所にあるため、入力とAjaxリクエストを検索サーバー側に調整するサービスを作成することをお勧めします。これは、2つの独立したコントローラ(searchboxと結果のためのものとフィルタのもの)から呼び出すことができます。

私が苦労している主なことは、ajaxが呼び出されたときに結果をリフレッシュすることです。 SearchCtrl Controllerに直接ajaxを置くと正常に動作しますが、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で定義されたプロパティを参照する必要があります。それを行う1つの方法は、あなたのコントローラに一度searchService.results$scope.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

ありがとうございました。それはパズルの欠けている部分だった 'angular.copy'部分でした。 –

+1

これは今私には完全に意味をなさない。私は3つの他のサービス/コントローラで作業していましたが、バインディングが壊れることはありませんでした。アレイ/オブジェクトを完全に交換する場合は、コピーを使用する必要があります!ありがとう! – LukeP

1

を問題は、あなたが更新されることはありませんということですあなたの範囲内のあなたの結果。そこにこれを行うには多くのアプローチがありますが、あなたの現在のコードに基づいて、あなたは最初の結果を返すように機能を見つけ、あなたのを変更できます。

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ができますが、機能が実際に結果を返すため原因であるとを見つけるようにしたいと思います。あなたの範囲にdoSearch()を呼び出すたびさておき、あなたは私があなたのjsfiddleを更新し、あなたのsearchService

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

から返されたため、現在の結果を更新したいと思います

設定私の考えは機能的ではありませんが、この問題をデバッグするのに役立ついくつかのコミットとログを追加しました。 http://jsfiddle.net/XTQSu/3/

+0

あなたの努力に感謝します。この例では、 'find'が結果を返すことを望んでいませんでした。なぜなら、結果は一つのコントローラで必要とされ、' find() 'は別のコントローラから呼び出されるからです。その結果は、コントローラではなくサービスにローカルに結果を保存する理由でした。欠落していたのは、サービス内の結果が使用されているコントローラにバインドされていることでした。マークが指摘したように、私は拘束された参照を持っていなかったので、それは更新していないのです。 'angular.copy() 'を使用すると、結果を更新したときにそのままバインディングが保持されます。繰り返していただき、ありがとうございました。 –

関連する問題