javascript - 在 Angular 过滤器中使用自定义过滤器、指令和 http GET 请求?

标签 javascript ajax angularjs filter

过去几周我一直在使用 angularjs,我有点无法理解如何让我的自定义指令、我的自定义过滤器在过滤器中添加 ajax 请求时相互配合(不确定是否添加过滤器内的 ajax 请求是个好主意)。

首先是一些背景:

我有一个项目列表和一个搜索字段。使用 Angular 的双向绑定(bind)创建列表并添加搜索/过滤功能对我来说真的很简单。现在,我希望仅在用户停止输入后才进行 Angular 过滤。我已经使用 underscore/lodash 提供的去抖功能实现了这一点。该过程的后续步骤是在用户停止输入后立即进行 - i) 抓取搜索文本 ii)发出http请求和 iii) 根据服务器的响应过滤列表,例如如果服务器按类别返回过滤器:foo 则使用 foo 进行过滤。到目前为止,我已经设法在用户停止输入时进行过滤,并根据一些硬编码类别(不使用 ajax)进行过滤。我添加了示例代码 http://plnkr.co/edit/s8sg5h1REd7n5opv0Vk2 - 它不是功能性的,但会提供我目前所做工作的背景。

我的问题是 - 1. 我在等待 ajax 完成时无法过滤 2. 我确定这不是解决我问题的最佳方法,请提出实现我目标的最佳方法。

我也无法在谷歌或 SO 上找到任何相关内容。


相关的 Html View

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

最佳答案

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

模板

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

关于javascript - 在 Angular 过滤器中使用自定义过滤器、指令和 http GET 请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21117487/

相关文章:

javascript - 一次滚动左 div 和右 div

javascript - .split() 在某些字符串上工作很奇怪

javascript - 如何从 JavaScript 文件中正确解压编码为 JSON 的 PHP 数组中的数据

javascript - 平均 : Getting Error 400 (Bad Request) on POST

javascript - 一种知道 Angular $http 何时为 "requesting"的方法

javascript - 如何获取数组中的value属性?

javascript - 无法区分 "similar"代码之间的区别

php - PHP 脚本没有响应

php - 动态生成的 Wordpress 所见即所得编辑器 (wp_editor) 无法正确显示

javascript - 如何让 ng-bind-html 编译 angularjs 代码