问题
Scenario
In an Angular2 app, I have some code in a component's view parent.component.html
looping through an array of items
and outputting each item
as a new component:
<div class="list-items">
<!-- In the attached image, this is displayed as a coloured card -->
<app-item *ngFor="let item of items" [item]="item"></app-list-slide>
</div>
Each item
has a category
key which is an array of ids (corresponding to the id of each category in a separate list).
// Item JSON
[
{
"id": 1,
"imageUrl": "https://via.placeholder.com/300x150/FF0000/FFFFFF?text=1",
"title": "One",
"categories": [ 1 ]
}
]
// Category JSON
[
{ "id": 1, "title": "Red Cards" },
{ "id": 2, "title": "Blue Cards" }
]
Requirement
The app needs to have a filter, dynamically generated by the categories (I might make this into a separate component):
<div class="items-filter">
<!-- In the attached image, this is displayed as a list of category buttons -->
<div *ngFor="let category of categories">
<a (click)="filterItemsByCategory(category)">{{ category.title }}</a>
</div>
<div class="btn-o">Reset</div>
</div>
When a category item is clicked, only the items corresponding to that category should be shown. Ideally, multiple categories could be clicked, but that can be for later.
All the examples I can find for filters, seem to use text input based filtering, and I'm not really sure where to start with this.
Final product should look like this:
Similar Example
Here is an example of something very similar to what I am trying to do (but the text input box would be replaced with the array of category buttons):
Article: http://www.freakyjolly.com/angular-4-5-typescript-create-filter-list-with-check-boxes-to-select-from-list/
Demo: https://freakyjolly.com/demo/AngularJS/Angular5FilterList/
Question
My question is either, does anyone know of any good working examples of what I am trying to do, or can anyone suggest a good place to start with this?
One option I can think of is to create classes on the component corresponding to the ids of the categories class="category-1 category-2"
but this seems messy.
Another option is using something like Masonary or Isotope, but a lot of the Angular libraries for these seem to be outdated: https://github.com/search?q=angular+masonry
Thanks
回答1:
This can be achieved by create a new variable, an array representing the filtered items and using *ngFor
with those filtered items. You'd use Array.prototype.filter along with Array.prototype.includes to filter items based on whether the id of the category is included in the item's categories array of id values:
Component:
import { Component } from "@angular/core";
import { Item } from "./item.ts";
import { Category } from "./category.ts";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
items: Item[] = [
{
id: 1,
imageUrl: "https://via.placeholder.com/300x150/FF0000/FFFFFF?text=1",
title: "One",
categories: [1]
}
];
categories: Category[] = [
{ id: 1, title: "Red Cards" },
{ id: 2, title: "Blue Cards" }
];
// Create a shallow copy of the items array
filteredItems: Item[] = [...this.items];
filterItemsByCategory(category: Category) {
this.filteredItems = this.items.filter((item: Item) => {
return item.categories.includes(category.id);
})
}
reset() {
this.filteredItems = [...this.items];
}
}
Template:
<div class="items-filter">
<!-- In the attached image, this is displayed as a list of category buttons -->
<div *ngFor="let category of categories">
<button type="button" (click)="filterItemsByCategory(category)">{{ category.title }}</button>
</div>
<button type="button" (click)="reset()" class="btn-o">Reset</button>
</div>
<div class="list-items">
<!-- In the attached image, this is displayed as a coloured card -->
<app-item *ngFor="let item of filteredItems" [item]="item">
</app-item>
</div>
Here is an example in action. If your date is async, which it most likely is in your actual application, you can use *ngIf
and/or defaults to empty arrays []
to avoid trying to perform array operations on undefined/null.
Also, it's recommend to avoid using <a>
elements as buttons, and instead just use <button>
elements. Also, as mentioned in a comment, the angular team recommends NOT using pipes for filtering and/or sorting, so I'd avoid doing what the articles you link suggest.
Hopefully that helps!
来源:https://stackoverflow.com/questions/58740256/how-can-i-implement-a-category-filter-in-angular2