Как я могу реализовать «фильтр категории» в Angular2 - PullRequest
2 голосов
/ 07 ноября 2019

Сценарий

В приложении Angular2 у меня есть некоторый код в представлении компонента parent.component.html, проходящий через массив items и выводящий каждый item в качестве нового компонента:

<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>

Каждый item имеет ключ category, который представляет собой массив идентификаторов (соответствует идентификатору каждой категории в отдельном списке).

// 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" }
]

Требование

В приложении должен быть фильтр, динамически генерируемый по категориям (я мог бы сделать это отдельным компонентом):

<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>

При нажатии на элемент категории должны отображаться только элементы, соответствующие этой категории. ,В идеале можно щелкнуть несколько категорий, но это может быть сделано позже.

Все примеры, которые я могу найти для фильтров, похоже, используют фильтрацию на основе ввода текста, и я не совсем уверен, с чего начать.

Конечный продукт должен выглядеть следующим образом: end product

Аналогичный пример

Вот пример чего-то очень похожего на то, что я пытаюсьсделать (но поле ввода текста будет заменено массивом кнопок категорий):

Артикул: http://www.freakyjolly.com/angular-4-5-typescript-create-filter-list-with-check-boxes-to-select-from-list/

Демо: https://freakyjolly.com/demo/AngularJS/Angular5FilterList/

Вопрос

У меня вопрос: кто-нибудь знает какие-нибудь хорошие рабочие примеры того, что я пытаюсь сделать, или кто-нибудь может предложить хорошее место, чтобы начать с этого?

Один вариант, который я могу придумать, - это создать классы на компоненте, соответствующем идентификаторам категорий class="category-1 category-2", но это выглядит грязно.

Другой вариант - использовать что-то вроде масонства или изотопа,но многие библиотеки Angular для них кажутся устаревшими: https://github.com/search?q=angular+masonry

Спасибо

1 Ответ

1 голос
/ 07 ноября 2019

Это может быть достигнуто путем создания новой переменной, массива, представляющего отфильтрованные элементы, и использования *ngFor с этими отфильтрованными элементами. Вы должны использовать Array.prototype.filter вместе с Array.prototype.includes для фильтрации элементов на основе того, включен ли идентификатор категории в массив категорий элементов значений идентификаторов:

Компонент:

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

Шаблон:

<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>

Вот пример action . Если ваша дата асинхронная, что, скорее всего, в вашем реальном приложении, вы можете использовать *ngIf и / или значения по умолчанию для пустых массивов [], чтобы избежать попыток выполнения операций над массивами с неопределенным / нулевым.

Кроме того, рекомендуется избегать использования элементов <a> в качестве кнопок, а вместо этого просто использовать элементы <button>. Кроме того, как уже упоминалось в комментарии, угловая команда рекомендует НЕ использовать каналы для фильтрации и / или сортировки , поэтому я не буду делать то, что предлагают ссылки, на которые вы ссылаетесь.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...