过去几周我一直在研究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;
};
}]);
答案 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;
};
}]);