简体   繁体   中英

Angular.js and server-side search - how to, best practices

In my app I had simple angular.js filter and it worked fine, but now I need to integrate server-side search. I have endpoint for this and I created directive which watches query in input and makes request to server returning results:

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

...

However the problem is in scope . As you see I'm writing results to parent scope items because I need the search results stay on the same page with same controller (as it was like in client-side filter):

common template for several controllers and search results:

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

So after representing results of server-side search query, when clearing input field I need somehow to return all items that were represented before search and currently cannot find optimal solution for this..

Maybe someone made something similar before?

Not sure if this is a good way to do it but I've got a directive listing students (optionally for a course) that gets data from a factory that in turn uses $resource to fetch data. Was fiddling around with it and like I say before not sure if this is the right way either.

Seems to work so I post the code here.

The template /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()">

The directive:

// 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);
              }
            };
          }
        ]);

The function:

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

The factory (called dataProvider), used $q before to return a promise and resolve it but it seems that with $resource you can just return the $resource and data will bind when a result is returned.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM