パフォーマンスに問題があり、解決できないでいます。インスタントサーチはありますが、keyup()
のたびに検索を開始するので、ややラグがあります。
JS:
var App = angular.module('App', []);
App.controller('DisplayController', function($scope, $http) {
$http.get('data.json').then(function(result){
$scope.entries = result.data;
});
});
HTMLです。
<input id="searchText" type="search" placeholder="live search..." ng-model="searchText" />
<div class="entry" ng-repeat="entry in entries | filter:searchText">
<span>{{entry.content}}</span>
</div>
JSONデータはそれほど大きくなく、300KBしかありません。私が達成しなければならないことは、キーストロークごとにアクションを実行するのではなく、ユーザーが入力を終えるのを待つために、検索に~1秒の遅延をかけることだと思います。AngularJSは内部的にこれを行っていますが、このサイトのドキュメントや他のトピックを読んでも、具体的な答えを見つけることができませんでした。
インスタント検索を遅らせるにはどうしたらいいのか、何かヒントをいただければ幸いです。
UPDATE(アップデイト
Angular 1.3では、モデルにデバウンスのオプションを追加するだけで、これまで以上に簡単にできるようになりました。
<input type="text" ng-model="searchStr" ng-model-options="{debounce: 1000}">
プランカーを更新しました。 http://plnkr.co/edit/4V13gK
ngModelOptionsに関するドキュメントです。
https://docs.angularjs.org/api/ng/directive/ngModelOptions
**古い方法ですが
angular本体以外の依存関係がない別の方法を紹介します。
タイムアウトを設定し、現在の文字列と過去のバージョンを比較して、両方が同じであれば検索を実行します。
$scope.$watch('searchStr', function (tmpStr)
{
if (!tmpStr || tmpStr.length == 0)
return 0;
$timeout(function() {
// if searchStr is still the same..
// go ahead and retrieve the data
if (tmpStr === $scope.searchStr)
{
$http.get('//echo.jsontest.com/res/'+ tmpStr).success(function(data) {
// update the textarea
$scope.responseData = data.res;
});
}
}, 1000);
});
と表示され、これがビューに入ります。
<input type="text" data-ng-model="searchStr">
<textarea> {{responseData}} </textarea>
必須のプランカーです。 http://plnkr.co/dAPmwf
(Angular 1.3の解決策は以下の回答を参照してください)。
ここでの問題は、モデルが変更されるたびに検索が実行されることで、それは入力に対するすべてのキーアップアクションです。
もっとすっきりとした方法があると思いますが、おそらく最も簡単な方法は、フィルタが動作するコントローラ内で定義された$scopeプロパティを持つようにバインディングを変更することでしょう。そうすれば、$scope 変数の更新頻度を制御することができます。以下のような感じです。
JS:
var App = angular.module('App', []);
App.controller('DisplayController', function($scope, $http, $timeout) {
$http.get('data.json').then(function(result){
$scope.entries = result.data;
});
// This is what you will bind the filter to
$scope.filterText = '';
// Instantiate these variables outside the watch
var tempFilterText = '',
filterTextTimeout;
$scope.$watch('searchText', function (val) {
if (filterTextTimeout) $timeout.cancel(filterTextTimeout);
tempFilterText = val;
filterTextTimeout = $timeout(function() {
$scope.filterText = tempFilterText;
}, 250); // delay 250 ms
})
});
HTMLです。
<input id="searchText" type="search" placeholder="live search..." ng-model="searchText" />
<div class="entry" ng-repeat="entry in entries | filter:filterText">
<span>{{entry.content}}</span>
</div>
debounced / throttled model updates for angularjs :
あなたのケースでは、jsfiddleのコードで以下のようにディレクティブを使用する以外にはありません。
<input
id="searchText"
type="search"
placeholder="live search..."
ng-model="searchText"
ng-ampere-debounce
/>
基本的には、 http://benalman.com/projects/jquery-throttle-debounce-plugin/ を利用した "ng-ampere-debounce" という名前の angular ディレクティブ1つで構成される小さなコードで、任意の dom 要素にアタッチすることができます。このディレクティブは、アタッチされたイベントハンドラの順番を入れ替えて、イベントをスロットルするタイミングを制御することができます。
次のような用途に使用できます。
ご覧ください:
このディレクティブはOrangevolt Ampereフレームワーク(https://github.com/lgersman/jquery.orangevolt-ampere)の一部になります。