以下HTML,Javascript和JSON正确呈现,但过滤器根本不起作用。我们做错了什么?
<div data-ng-controller="dashboard_controller">
<h1>
Catalogs
<input type="text" data-ng-model="catalog_filter" placeholder="Filter Distributors">
</h1>
<div class="catalogs_listing">
<ul data-ng-repeat="catalog in catalogs | filter:catalog_filter">
<li><a href="{{catalog.distributor_id}}/d/products/catalog_view/{{catalog.uid}}">
<div class="catalog_thumb">
<div class="catalog_thumb_image">
<img src="{{catalog.thumb_image}}" />
</div>
</div>
<div class="catalog_info">
<h2>{{distributors[catalog.distributor_id].name}}
<span>{{catalog.products_count}}p</span>
</h2>
<p>{{catalog.name}}</p>
</div>
</a>
</li>
</ul>
</div>
</div>
Javascript:
app.controller('dashboard_controller', function ($scope, $http) {
$http.get('./api/distributors/my').then(function (res) {
$scope.distributors = res.data;
});
$http.get('./api/dashboard/catalogs').then(function (res) {
$scope.catalogs = res.data;
});
});
这两个JSON:
API /经销商/我的:
{
"data": {
"9kkE1sL8vXSZMVaL": {
"created": "1346840145.22",
"uid": "9kkE1sL8vXSZMVaL",
"created_by": "3W7AoIQHTtvPauaK",
"name": "Nikee",
"description": "Just do it",
"image_file": "LogoNike.jpg",
"modified": "1368443518.3894",
"modified_by": "3W7AoIQHTtvPauaK",
"currency": "gbp"
},
"1OBKUhpb8srwHVVb": {
"created": "1346840213.41",
"uid": "1OBKUhpb8srwHVVb",
"created_by": "3W7AoIQHTtvPauaK",
"name": "Zappos",
"description": "The webs most popular shoe store",
"image_file": "zappos.jpg",
"modified": "1347006513.93",
"modified_by": "3W7AoIQHTtvPauaK",
"currency": null
},
"qHPXDp5lSQuz9z3Q": {
"created": "1346840305.78",
"uid": "qHPXDp5lSQuz9z3Q",
"created_by": "3W7AoIQHTtvPauaK",
"name": "Kitchenaid",
"description": "For the way it's made",
"image_file": "kitchenaid_logo.gif",
"modified": "1346840305.78",
"modified_by": "3W7AoIQHTtvPauaK",
"currency": null
},
"9K4G8gE1sh4qpVG2": {
"created": "1346840443.32",
"uid": "9K4G8gE1sh4qpVG2",
"created_by": "3W7AoIQHTtvPauaK",
"name": "Unilever",
"description": "Create a better future",
"image_file": "Unilever-logo.jpg",
"modified": "1346842125.2",
"modified_by": "3W7AoIQHTtvPauaK",
"currency": null
},
"55ORaD7h0EMcaX82": {
"created": "1346840529.93",
"uid": "55ORaD7h0EMcaX82",
"created_by": "3W7AoIQHTtvPauaK",
"name": "Dell",
"description": "The power to do more",
"image_file": "dell-logo.jpg",
"modified": "1346840529.93",
"modified_by": "3W7AoIQHTtvPauaK",
"currency": null
},
"2LHf5ZipYjA2PdXu": {
"created": "1352084334.37",
"uid": "2LHf5ZipYjA2PdXu",
"created_by": "3MO4JyiB9rMWTfBu",
"name": "Online Retailer",
"description": "Online Retailer",
"image_file": "Home and Giftware.gif",
"modified": "1352954806.28",
"modified_by": "cu3OraVD7WclpLrX",
"currency": null
},
"MdTDL72ynFySuUCR": {
"created": "1352870158.83",
"uid": "MdTDL72ynFySuUCR",
"created_by": "1JiAF71w5VPHGgJe",
"name": "Uniuniform",
"description": "Uniform Suppliers",
"image_file": "CWLogo.png",
"modified": "1358317144.85",
"modified_by": "sv3HuiiRbiuHWkul",
"currency": null
},
"oyYmdDcod9fseZng": {
"created": "1352934703.42",
"uid": "oyYmdDcod9fseZng",
"created_by": "cu3OraVD7WclpLrX",
"name": "Heidy Pharmaceuticals",
"description": "Pharmaceutical Solutions",
"image_file": "heidy.jpg",
"modified": "1352934703.43",
"modified_by": "cu3OraVD7WclpLrX",
"currency": null
},
"Kfs4HdFUfz6j2l2I": {
"created": "1352953682.22",
"uid": "Kfs4HdFUfz6j2l2I",
"created_by": "cu3OraVD7WclpLrX",
"name": "xxx",
"description": "Online Retailer",
"image_file": "xxx.gif",
"modified": "1352953828.34",
"modified_by": "cu3OraVD7WclpLrX",
"currency": null
},
"g2qRqUWvPSLRvLQr": {
"created": "1352953924.68",
"uid": "g2qRqUWvPSLRvLQr",
"created_by": "cu3OraVD7WclpLrX",
"name": "ddd",
"description": "Natural Product Retailer",
"image_file": "yes-to.jpg",
"modified": "1352953924.68",
"modified_by": "cu3OraVD7WclpLrX",
"currency": null
},
"bbSu3jpFhdkG3TJR": {
"created": "1352954016.22",
"uid": "bbSu3jpFhdkG3TJR",
"created_by": "cu3OraVD7WclpLrX",
"name": "llll",
"description": "Artificial Product Retailer",
"image_file": "l.jpg",
"modified": "1352954016.23",
"modified_by": "cu3OraVD7WclpLrX",
"currency": null
},
"X9xWF9VrRDqGWZ6S": {
"created": "1352954722.97",
"uid": "X9xWF9VrRDqGWZ6S",
"created_by": "cu3OraVD7WclpLrX",
"name": "zzz",
"description": "Toy Manufacturer",
"image_file": "zzz.jpg",
"modified": "1352954722.97",
"modified_by": "cu3OraVD7WclpLrX",
"currency": null
},
"02CCPuWtM6ZJVgiQ": {
"created": "1367741881.7113",
"uid": "02CCPuWtM6ZJVgiQ",
"created_by": "3W7AoIQHTtvPauaK",
"name": "test brand",
"description": "xxxx",
"image_file": null,
"modified": "1367741882.5129",
"modified_by": "3W7AoIQHTtvPauaK",
"currency": null
},
"GjsdgMCzp1n379j0": {
"created": "1369136484.1802",
"uid": "GjsdgMCzp1n379j0",
"created_by": "3W7AoIQHTtvPauaK",
"name": "testing all products",
"description": "just a test",
"image_file": null,
"modified": "1369136484.5298",
"modified_by": "3W7AoIQHTtvPauaK",
"currency": "usd"
},
"spVsxtJVroMkXQ1N": {
"created": "1370508658.353",
"uid": "spVsxtJVroMkXQ1N",
"created_by": "3W7AoIQHTtvPauaK",
"name": "pppp Import",
"description": "",
"image_file": null,
"modified": "1370508658.4394",
"modified_by": "3W7AoIQHTtvPauaK",
"currency": "usd"
}
}
API /仪表板/目录
{
"data": {
"UPf17vFhMhiM2yYl": {
"created": "1352960014.4",
"uid": "UPf17vFhMhiM2yYl",
"created_by": "3MO4JyiB9rMWTfBu",
"name": "All Products",
"description": "This catalog contains all of your products",
"modified": "1352960014.4",
"modified_by": "3MO4JyiB9rMWTfBu",
"distributor_id": "9kkE1sL8vXSZMVaL",
"image": null,
"start": null,
"end": null,
"is_archived": null,
"products_count": "0",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"ZUfcKpz0VrJZZZvW": {
"created": "1354172792.79",
"uid": "ZUfcKpz0VrJZZZvW",
"created_by": "ORIGWlEFxbuE945J",
"name": "test catalog",
"description": "",
"modified": "1354172792.79",
"modified_by": "ORIGWlEFxbuE945J",
"distributor_id": "9kkE1sL8vXSZMVaL",
"image": null,
"start": null,
"end": null,
"is_archived": null,
"products_count": "0",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"6YoSSDCzLH8gEokf": {
"created": "1360706477.5283",
"uid": "6YoSSDCzLH8gEokf",
"created_by": "3W7AoIQHTtvPauaK",
"name": "xxxx",
"description": "",
"modified": "1360706477.5312",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "9kkE1sL8vXSZMVaL",
"image": null,
"start": null,
"end": null,
"is_archived": null,
"products_count": "3",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"4AwqE7iTNQmjSBED": {
"created": "1360794567.8451",
"uid": "4AwqE7iTNQmjSBED",
"created_by": "3W7AoIQHTtvPauaK",
"name": "All Products",
"description": null,
"modified": "1360794567.8454",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "4AwqE7iTNQmjSBED",
"image": null,
"start": null,
"end": null,
"is_archived": null,
"products_count": "1",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"02CCPuWtM6ZJVgiQ": {
"created": "1367741881.7916",
"uid": "02CCPuWtM6ZJVgiQ",
"created_by": "3W7AoIQHTtvPauaK",
"name": "All Products",
"description": null,
"modified": "1367741881.7919",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "02CCPuWtM6ZJVgiQ",
"image": null,
"start": null,
"end": null,
"is_archived": null,
"products_count": "2095",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"9kkE1sL8vXSZMVaL": {
"created": "1368165852.0352",
"uid": "9kkE1sL8vXSZMVaL",
"created_by": "3W7AoIQHTtvPauaK",
"name": "All Products",
"description": null,
"modified": "1368165852.0361",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "9kkE1sL8vXSZMVaL",
"image": null,
"start": null,
"end": null,
"is_archived": null,
"products_count": "26",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"ZmSiqOK2C2Sq3MWB": {
"created": "1368958571.9548",
"uid": "ZmSiqOK2C2Sq3MWB",
"created_by": "3W7AoIQHTtvPauaK",
"name": "Test Catalog",
"description": "",
"modified": "1368958571.9581",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "02CCPuWtM6ZJVgiQ",
"image": null,
"start": "0",
"end": "0",
"is_archived": "1",
"products_count": "0",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"flzoMbizDDTDpjgc": {
"created": "1368958778.8623",
"uid": "flzoMbizDDTDpjgc",
"created_by": "3W7AoIQHTtvPauaK",
"name": "xzczxc",
"description": "",
"modified": "1368958778.8637",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "02CCPuWtM6ZJVgiQ",
"image": null,
"start": "0",
"end": "0",
"is_archived": "0",
"products_count": "29",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"KfRJHxp7jBnBGCJ5": {
"created": "1369219487.4418",
"uid": "KfRJHxp7jBnBGCJ5",
"created_by": "3W7AoIQHTtvPauaK",
"name": "hhh",
"description": "",
"modified": "1369219487.4433",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "9kkE1sL8vXSZMVaL",
"image": null,
"start": "0",
"end": "0",
"is_archived": "0",
"products_count": "7",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"spVsxtJVroMkXQ1N": {
"created": "1370508658.3567",
"uid": "spVsxtJVroMkXQ1N",
"created_by": "3W7AoIQHTtvPauaK",
"name": "All Products",
"description": null,
"modified": "1370508658.3575",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "spVsxtJVroMkXQ1N",
"image": null,
"start": "0",
"end": "0",
"is_archived": "0",
"products_count": "343",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"1OBKUhpb8srwHVVb": {
"created": "1370857435.5606",
"uid": "1OBKUhpb8srwHVVb",
"created_by": "3W7AoIQHTtvPauaK",
"name": "All Products",
"description": null,
"modified": "1370857435.5612",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "1OBKUhpb8srwHVVb",
"image": null,
"start": "0",
"end": "0",
"is_archived": "0",
"products_count": "4",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"wXMHFdPyiXFBuRjJ": {
"created": "1370864864.1247",
"uid": "wXMHFdPyiXFBuRjJ",
"created_by": "3W7AoIQHTtvPauaK",
"name": "x",
"description": "",
"modified": "1370864864.1278",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "spVsxtJVroMkXQ1N",
"image": null,
"start": "0",
"end": "0",
"is_archived": "0",
"products_count": "10",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"GjsdgMCzp1n379j0": {
"created": "1371116610.6898",
"uid": "GjsdgMCzp1n379j0",
"created_by": "3W7AoIQHTtvPauaK",
"name": "All Products",
"description": null,
"modified": "1371116610.6902",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "GjsdgMCzp1n379j0",
"image": null,
"start": "0",
"end": "0",
"is_archived": "0",
"products_count": "2095",
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
},
"gvWLNWwsI3B7mnCU": {
"created": "1371116669.5872",
"uid": "gvWLNWwsI3B7mnCU",
"created_by": "3W7AoIQHTtvPauaK",
"name": "All Products",
"description": null,
"modified": "1371116669.5877",
"modified_by": "3W7AoIQHTtvPauaK",
"distributor_id": "gvWLNWwsI3B7mnCU",
"image": null,
"start": "0",
"end": "0",
"is_archived": "0",
"products_count": 0,
"thumb_image": "resources/media/default_image.jpg.thumbs/165x165.jpg"
}
}
答案 0 :(得分:42)
角度滤镜无法处理对象的对象作为输入。 ng-repeat可以渲染它们,但过滤器需要一组对象。解决此问题的最简单方法是让服务器返回没有命名键的数组。您还可以在每次请求后以角度转换响应(更昂贵)。
答案 1 :(得分:34)
正如Narretz已经提到的,Angular过滤器无法处理对象的对象作为输入。但是您可以编写自己的简单过滤器,将对象的对象转换为对象数组。您可以通过链接使用 array 过滤器后面的角度过滤器。
<ul data-ng-repeat="catalog in catalogs | array | filter:catalog_filter">
您的数组过滤器可能就像这样简单:
app.filter('array', function() {
return function(items) {
var filtered = [];
angular.forEach(items, function(item) {
filtered.push(item);
});
return filtered;
};
});
答案 2 :(得分:3)
假设您想使用经销商名称过滤目录,那么以下自定义过滤器可以完成这项工作:
<div data-ng-controller="dashboard_controller">
<h1>
Catalogs
<input type="text" data-ng-model="catalog_filter" placeholder="Filter Distributors">
</h1>
<div class="catalogs_listing">
<ul data-ng-repeat="catalog in catalogs | distributorName: catalog_filter:distributors">
<li> <a href="{{catalog.distributor_id}}/d/products/catalog_view/{{catalog.uid}}">
<div class="catalog_thumb">
<div class="catalog_thumb_image">
<span>demo - no image</span>
</div>
</div>
<div class="catalog_info">
<h2>{{distributors[catalog.distributor_id].name}} <span>{{catalog.products_count}}p</span></h2>
<p>{{catalog.name}}</p>
</div>
</a>
</li>
</ul>
</div>
</div>
app.filter('distributorName', function() {
return function(items, filterValue, distributors) {
if (!filterValue){
return items;
}
var result = {};
angular.forEach(items, function(value, key) {
var distributor = distributors[value.distributor_id];
if (distributor && distributor.name && distributor.name.toLowerCase().indexOf(filterValue.toLowerCase()) > -1){
result[key] = value;
}
});
return result;
};
});
JSFiddle with local data:http://jsfiddle.net/alfrescian/p8zgp/
答案 3 :(得分:2)
非常有用的知道......这是alfrescian解决方案的更通用版本,用子键过滤对象列表。
app.filter('objFilter', function() {
return function(items, filter) {
if (!filter){
return items;
}
var result = {};
angular.forEach( filter, function(filterVal, filterKey) {
angular.forEach(items, function(item, key) {
var fieldVal = item[filterKey];
if (fieldVal && fieldVal.toLowerCase().indexOf(filterVal.toLowerCase()) > -1){
result[key] = item;
}
});
});
return result;
};
});
然后您可以拥有多个过滤器框,例如
<input ng:model="filter.firstName"/>
<input ng:model="filter.lastName"/>
<input ng:model="filter.email"/>
您的ng-repeat
看起来像这样
<ul ng:repeat="cust in customers | objFilter: filter">
<li>
<a href="mailto:{{cust.email}}">{{cust.firstName}} {{cust.lastName}}</a>
</li>
</ul>
答案 4 :(得分:1)
您可以使用将对象转换为数组的toArrayFilter,以便常规过滤器可以使用它。
在你的情况下,它将是:
<div ng-repeat="catalog in catalogs | toArray | filter:catalog_filter">
{{ catalog.$key }} - {{ catalog.someProp }}
<!-- code -->
</div>
答案 5 :(得分:1)
鉴于,这是一个极端的案例,但我想我会分享。
您拥有数据结构;它需要是一个集合,但由于预期的增长,复杂性或其他约束,它需要非常 SOLID 基础和自己的方法。因此,您决定将此对象原型化为数组。
var OrdersDataModel = function OrdersDataModel(orders) {
var thus = this;
var orders = orders || [];
function loadData(data) {
this.splice.apply(this, [0, this.length].concat(data || orders));
return this;
}
function serialize() {
var serialized = JSON.stringify(this);
return serialized;
}
function marshalData() {
var marshalled = JSON.parse(this.serialize());
return marshalled;
}
// export precepts
this.load = loadData;
this.serialize = serialize;
this.marshalData = marshalData;
return this;
};
OrdersDataModel.prototype = new Array();
这可能符合您的需求并在ng-repeat
中表现良好 - 直到需要filter
您的&#34;数组&#34;:
<element ng-repeat="order in orders | filter:q" />
你的过滤器会失败(可能只是因为类型检查),你可能会浪费一点时间。
就我而言,可以通过从
修改我的serialize
方法轻松解决
var serialized = JSON.stringify(this);
- 到 -
var serialized = JSON.stringify(this.slice(0));
尽管如此,实现目标的更好方法是使用装饰器模式或构造函数 - 劫持来装饰数组:
而不是:
OrdersDataModel.prototype = new Array();
...
this.orders = new OrdersDataModel();
this.orders.load(serverData);
- 使用 -
this.orders = OrdersDataModel.apply([]);
this.orders.load(serverData);
其中很多可能看起来有点无关紧要,但我希望这个(及其包含的模块/控制器)能够快速扩展,因此我尽可能地坚持使用SOLID来保持气密性。< / p>
希望这可以节省你一些时间!
答案 6 :(得分:1)
角度过滤器无法处理对象的对象作为输入,但是,要解决您面临的问题,可以向catalog_filter添加监视。如下:
$scope.$watch('catalog_filter', function (value) {
regex = new RegExp($scope.catalog_filter);
if (!$scope.catalog_filter) return true;
return regex.test(catalog.uid); /* can create multiple conditions based on the requirement*/
});
执行此操作时,过滤器会对输入文本起作用,并在文本更改时进行过滤。