1

私のアプリには単純な angular.js フィルターがあり、正常に機能しましたが、サーバー側の検索を統合する必要があります。このためのエンドポイントがあり、入力でクエリを監視し、結果を返すサーバーにリクエストを行うディレクティブを作成しました。

html:

<search ng-model="query"></search>

js:

...
        restrict: 'E',
        scope: {
            ngModel: '='
        },
        template: '<input type="text" ng-model="ngModel" />',
        link: function (scope, elem, attrs) {
            var timer = false;
            scope.$watch('ngModel', function (value) {
                if (timer) {
                    $timeout.cancel(timer);
                }
                timer = $timeout(function () {
                    if (value) {
                        scope.$parent.items = rest.query({ resource: 'search', query: value });
                    }
                }, 1000);
            });
        }

...

ただし、問題は範囲内です。ご覧のとおり、検索結果を同じコントローラーで同じページにとどめる必要があるため、結果を親スコープ アイテムに書き込んでいます (クライアント側フィルターの場合と同様)。

複数のコントローラーと検索結果の共通テンプレート:

<ul class="items">
  <li class="item item{{$index+1}}" ng-repeat="item in items">
  ...
  </li>
</ul>

したがって、サーバー側の検索クエリの結果を表した後、入力フィールドをクリアするときに、検索前に表されたすべてのアイテムを何らかの形で返す必要があり、現在これに対する最適なソリューションを見つけることができません..

誰かが以前に似たようなものを作ったのではないでしょうか?

4

1 に答える 1

2

これが良い方法かどうかはわかりませんが、データ$resourceをフェッチするために使用するファクトリからデータを取得する学生 (オプションでコース用) をリストするディレクティブがあります。それをいじっていましたが、前に言ったように、これが正しい方法であるかどうかもわかりません。

動作するように見えるので、ここにコードを投稿します。

テンプレート/partials/v001/student-course-list.html:

Search: <input data-ng-model="query" data-ng-change="search()"/>
Only for this course <input type="checkbox" name="courseid"
   data-ng-model="courseid" data-ng-change="search()">

ディレクティブ:

// list students (optional for course) both students and course
//   are initially set outside and passed through
angular.module('student').directive('studentCourseList',
        ['dataProvider',
          function(dataProvider) {
            return {
            restrict: 'A',
            //static in GAE so will be cached for a year
            //  need versioning
            templateUrl: '/partials/v001/student-course-list.html',
            scope: {
              course: '=',
              students: '='
            },
            link: function(scope, elem, attrs) {
              scope.search = functions.searchStudentsByName(
                dataProvider, scope);
              }
            };
          }
        ]);

関数:

//Containing controllers/directives DOM event handlers
//  Like ng-change for the search box and isInCourse checkbox
var functions = {
  searchStudentsByName: function(dataProvider, scope) {
    return function() {
      //half a second delay before starting search
      //  user may be typing several characters
      clearTimeout(scope.timeoutId);
      scope.timeoutId = setTimeout(function() {
        var sId=(scope.courseid)?scope.course.id:false,
        q=(scope.query)?scope.query:"";
        //can check q again if len<2 set it to ""
        //  this because isInCourse may have triggered this
        scope.students=dataProvider.searchStudentsByName(
                scope.query, sId);
      }, 500);
    };
  }
};

ファクトリ (dataProvider と呼ばれる) は、前に $q を使用して promise を返し、それを解決しましたが、$resource を使用すると、$resource を返すだけで、結果が返されたときにデータがバインドされるようです。

angular.module('dataProvider', []).
  factory('dataProvider', ['$resource','$q',function($resource,$q) { 
    //Anything having /app/student/ goes to google app server
    //   prefer to just add getstring on the url
    var StudentFromApp = $resource('/app/student/',
     {}
    );
    return {
     //course id is optional in case only student for course
     searchStudentsByName:function(sName,cid){
        return StudentFromApp.query(
          {courseid:cid,studentName:sName});
      }
    };
}]);
于 2013-10-10T08:36:44.300 に答える