在角度过滤器中使用自定义过滤器,指令和http GET请求?

时间:2014-01-14 15:37:14

标签: javascript ajax angularjs filter

过去几周我一直在研究angularjs,我有点无法理解如何制作自定义指令,我的自定义过滤器在过滤器中添加ajax请求时相互协作(不确定是否添加了内部过滤器中的ajax请求是个好主意。)

首先是一些背景:

我有一个项目列表和一个搜索字段。使用angular的双向绑定创建列表并添加搜索/过滤功能对我来说非常简单。现在,我希望只有在用户停止输入后才会过滤角度。我使用下划线/ lodash提供的去抖功能实现了这一点。一旦用户停止输入,该过程的后续步骤 - i)抓住搜索文本 ii)发出http请求和 iii)根据来自服务器的响应过滤列表,例如,如果服务器按类别返回过滤器:foo然后使用foo过滤。到目前为止,我已经设法过滤,因为用户停止键入和过滤基于一些硬编码类别(不使用ajax)。我添加了示例代码http://plnkr.co/edit/s8sg5h1REd7n5opv0Vk2 - 它不起作用,但会提供我到目前为止所做的背景。

我的问题是 - 我在等待ajax完成时无法过滤 2.我确信这不是解决问题的最佳方法,请说明实现目标的最佳方法是什么。

此外,我无法在Google或SO上找到任何相关内容。


相关的Html视图

<my-input type="search" data-ng-model="ts.search" placeholder="search"></c1-input>

<ul data-ng-repeat="car in cars">
  <li>{{car.name}} </li>
</ul>

相关的javascript

app.controller('MainController', ['$scope', 'carsFactory', function ($scope, carsFactory) {
    $scope.cars = carsFactory.getCars();
    $scope.filteredCars = $scope.cars;
}]);

app.directive('myInput', function ($parse, $filter) {
  return {
    restrict: "E",
    replace: true,
    transclude: true,
    template: '<input ng-translude/>',
    compile: function (cElement, cAttrs) {
      var modelAccessor = $parse(cAttrs.ngModel);

      return function (scope, element, attrs, controller) {
        // Filter only after user has stopped typing
        scope.$watch(modelAccessor, _.debounce(function (val) {
          scope.typed = scope.typing;
          scope.$apply(function () {
            modelAccessor.assign(scope, val);
            scope.filteredCars = $filter('myFilter')(scope.cars, val);
          });
        }, 500))
      } 
    }
  }
});

app.factory('carsFactory',['$http', function ($http) {
  return {
    // This actually makes a ajax request
    getCars: function () {
      return cars;
    }
  }

  var cars = [{name: 'Focus ST', category: 'hatchback'}, 
  {name: 'Audi S5', category: 'coupe'},
  {name: 'Audi S4', category: 'sedan'},
  {name: 'Mazda 3', category: 'hatchback'},
  {name: 'Mazda 3', category: 'sedan'}]
}]);


app.filter('myFilter', ['$filter', function ($filter) {

  // should make http request
  // should grab response and apply custom filters on the transactions

  function makeHttpRequest (cars, searchText) {
    // Here it should make a http request and return category.
    // Next, filter should be applied based on category
    return cars;
  }

  return function (cars, searchText) {
    if (searchText) {
      cars =  makeHttpRequest(cars, searchText);
    }
    return cars;
  };
}]);

1 个答案:

答案 0 :(得分:2)

以下是我解决问题的方法。如果我错了,请纠正我。

模板

<h2>Cars</h2>

<my-input type="search" data-ng-model="myModel.searchField" placeholder="search"></my-input>

<ul data-ng-repeat="car in myModel.filteredCars">
   <li>{{car.name}} </li>
</ul>

脚本

// Defining app with route dependency
var app = angular.module("myApp", ["ngRoute"]);
app.config(['$routeProvider', '$locationProvider', function ($routeProvider,  $locationProvider) {
  $routeProvider
    .when('/t', {
        controller: 'MainController',
        templateUrl: 'main.html'
      })
    .otherwise({ redirectTo: '/t' });

    $locationProvider.html5Mode(true);
}]);

app.controller('MainController', ['$scope', 'carsFactory','categoryFactory','$filter', function ($scope, carsFactory, categoryFactory, $filter) {
    $scope.myModel.searchField = {};
    $scope.myModel.cars = carsFactory.getCars();
    $scope.myModel.filteredCars = $scope.myModel.cars;
    $scope.myModel.search = function (query) {
      if (!query) return false;

      var filterCat = categoryFactory.getFilterCategory(query);

      $scope.myModel.filteredCars = $filter('myFilter')($scope.myModel.cars, filterCat.category);

    }
}]);

app.directive('myInput', function ($parse, $filter) {
  return {
    restrict: "E",
    replace: true,
    transclude: true,
    template: '<input ng-translude/>',
    link: function (scope, lElement, lAttrs) {
      var modelAccessor = $parse(cAttrs.ngModel);

      scope.$watch(modelAccessor, _.debounce (function (val) {
        scope.$apply(function () {
          scope.myModel.search(val);
        });
      }, 500));
    }
  };
});

app.factory('carsFactory',['$http', function ($http) {
  var cars = [{name: 'Focus ST', category: 'hatchback'}, 
  {name: 'Audi S5', category: 'coupe'},
  {name: 'Audi S4', category: 'sedan'},
  {name: 'Mazda 3', category: 'hatchback'},
  {name: 'Mazda 3', category: 'sedan'}];

  return {
    // This actually makes a ajax request and returns list of available cars
    getCars: function () {
      return cars;
    }
  }


}]);

app.factory('categoryFactory', function () {
  var category = {category: "sedan"};

  return {
  // make an ajax request with query parameter and return sample response
    getFilterCategory: function (query) {
      return category;
    }
  }

});


app.filter('myFilter', ['$filter', function ($filter) {

  function filter(cars, category) {
// Assuming we are doing some complex calculations here before we actually filter
    return $filter('filter')(cars, {category: category});
  }

  return function (cars, category) {

    cars =  filter(cars, category);

    return cars;
  };
}]);