简体   繁体   English

如何过滤 Angular 中的类别 9

[英]How to filter categories in Angular 9

I want to filter by categories in a Webshop.我想在网上商店中按类别过滤。 Actually I stuck with a tutorial from Mosh because I have no Error Message in Browser or Command Prompt but nothing is filtered or even showed.实际上,我坚持使用 Mosh 的教程,因为我在浏览器或命令提示符中没有错误消息,但没有任何内容被过滤甚至显示。 I am a absolute beginner in Angular and/or typescript so pls be kind^^ I tried to resolve the problem by my own for ages but it doesn´t work.我是 Angular 和/或 typescript 的绝对初学者,所以请善待^^我试图自己解决这个问题已经很久了,但它不起作用。 Please help me out.请帮帮我。

Thats my code:那是我的代码:

products.component.ts: products.component.ts:

export class ProductsComponent {

 products: Product[]= [];
 filteredProducts: Product[] = [];
categories$: Observable<any>;
category: string;
products$: Observable<any>;


 constructor(
    route: ActivatedRoute,
    productService: ProductService, 
    categoryService: CategoryService) {
    this.filteredProducts;

productService.getAll().subscribe (products => this.products);



//Shows Categories in View
    this.categories$ = categoryService.getAll();
    route.queryParamMap.subscribe(params => {
      this.category = params.get('category');
      this.categories$.subscribe(res => console.log (res)); //Console.log  5 Categories Observable



      //Setting the filtered Products Array
      this.filteredProducts = (this.category) ? 
       this.products.filter(p => {
         return p.category === this.category;
       }) : 
      this.products;
      console.log(this.filteredProducts); // Console.log FilteredProducts Array
    });

   }

 }

products.component.html: products.component.html:

<div class="row">
  <div class="col-3">
    <div class="list-group">


      <!-- Bei queryParams c.name auswählbare Kategorien / bei c.key nicht sowie bei c.$key nicht-->
      <a *ngFor="let c of categories$ | async "
      routerLink= "/"
      [queryParams]="{ category: c.name }"  
       class="list-group-item list-group-item-action"
       [class.active]="category === c.name">
        {{ c.name }}
      </a>
    </div>  
  </div>
  <div class="col-9">
    <div class="row">
      <ng-container *ngFor="let product of filteredProducts ; let i = index">
        <div class="col">
          <div class="card" style="width: 15rem;">
          <img [src]="product.imageUrl" class="card-img-top" alt="Card image cap">
          <div class="card-body">
            <h5 class="card-title">{{ product.title }}</h5>
            <p class="card-text">{{ product.price | currency: 'EUR' }}</p>
            <a href="#" class="btn btn-primary">Add to Cart</a>
          </div>
        </div>
      </div>
      <div *ngIf="(i + 1) % 2 === 0" class="w-100"></div>
      </ng-container>
    </div>
  </div>
</div>

在蓝色边框框中,应显示单击类别的项目

Here productService.getAll() method will take some time to fetch data from API, but route.queryParamMap will get executed immediately, while this observable is subscribed this.products object will be empty, that's why it is not able to filter.这里productService.getAll()方法从 API 获取数据需要一些时间,但是route.queryParamMap会立即执行,而这个 observable 订阅this.products object 将是空的,这就是它无法过滤的原因。 also you have not initialized this.products = products , in subscription.您还没有在订阅中初始化this.products = products To fix all this you can implement it as below:要解决所有这些问题,您可以按如下方式实现:

    export class ProductsComponent {

     products: Product[]= [];
     filteredProducts: Product[] = [];
    categories$: Observable<any>;
    category: string;
    products$: Observable<any>;


     constructor(
        route: ActivatedRoute,
        productService: ProductService, 
        categoryService: CategoryService) {
        this.filteredProducts = [];


        //Shows Categories in View
        this.categories$ = categoryService.getAll();
        route.queryParamMap.subscribe(params => {
          this.category = params.get('category');
            });


    productService.getAll().subscribe (products => {
                   this.products = products;
                             //Setting the filtered Products Array
                   this.filteredProducts = (this.category) ? 
                   this.products.filter(p => {
                      return p.category === this.category;
                   }) : this.products;
                   console.log(this.filteredProducts); // Console.log FilteredProducts Array
}); 
       }

     }

This is what I get if i console.log as follows: productService.getAll().subscribe (products => { console.log(products); this.products = products;});如果我 console.log 如下所示,这就是我得到的: productService.getAll().subscribe (products => { console.log(products); this.products = products;});

在此处输入图像描述 and in the CMD:在 CMD 中:

在此处输入图像描述

well, there're some mistakes, the first is that you has嗯,有一些错误,首先是你有

productService.getAll().subscribe (products => this.products);

must be一定是

productService.getAll().subscribe (products => this.products=products);

But this not work becouse is an async call.但这不起作用,因为是异步调用。

So, first change your productService "caching" the products.因此,首先更改您的 productService“缓存”产品。 Your service like你的服务喜欢

products:any[]
getAll()
{
    return products?of(product):
           this.httpClient.get("your-url").pipe(
              tap(res=>this.products=res;
           )
}

We use of from 'rxjs' and tap from 'rxjs/operators'我们使用from 'rxjs' 并点击from 'rxjs/operators'

This make that getProducts return an Observable of products.这使得 getProducts 返回一个 Observable 产品。 The first time is called, "products" are undefinned, so return the response of the httpClient.get.第一次调用,“产品”是未定义的,所以返回httpClient.get的响应。 The tap make that procuts get the value, so the second time is called the variable products are used. procuts的tap make得到值,所以第二次被称为变量产品使用。

The second error is used the "constructor" use ngOnInit to subscribe to route.queryParamMap.第二个错误是使用“构造函数”使用 ngOnInit 订阅 route.queryParamMap。

ngOnInit()
{
   this.route.queryParamMap.subscribe(params => {
      this.category = params.get('category');

      //here you get all the products
      this.productService.getAll().subscribe (
         products => this.products=products);
         //Setting the filtered Products Array
         this.filteredProducts = (this.category) ? 
             this.products.filter(p => {
              return p.category === this.category;
         }) : 
         this.products;
         console.log(this.filteredProducts); // Console.log FilteredProducts Array
      });
}

Well, another aproach is using switchMap and make that filteredProducts becomes an observable (then we use filteredProduct$ | async)好吧,另一种方法是使用 switchMap 并使过滤产品成为可观察的(然后我们使用过滤产品$ |异步)

   this.filteredProduct$=this.route.queryParamMap.pipe(
     switchMap(params=>{
       this.category=params.get('category');
       return this.productService.getAll().pipe( 
          switchMap(products=>{
              const filteredProduct=!this.category?products:
                   products.filter(p => {
                      return p.category === this.category;
                    }) : 
             return of(filteredProduct):

          })
       )
     })
   ) 

NOTE: I don't check the code but this is the idea, I hope this can be usefull注意:我不检查代码,但这是我的想法,我希望这可以有用

The problem exist in filtering part, when you gonna filter your products on the base of category, then actually, it did not filter.过滤部分存在问题,当您要根据类别过滤产品时,实际上并没有过滤。 The reason is that because your program did not get category of product in p.category .原因是因为您的程序没有在p.category中获得产品类别。 Because you are using latest angular as well as latest firebase.因为您使用的是最新的 angular 以及最新的 firebase。 So you should use p.payload.val().category .所以你应该使用p.payload.val().category Then it will compare your category with the this.category .然后它将您的类别与this.category进行比较。

Try the given code尝试给定的代码

productService.getAll().pipe(switchMap(products => {
    this.products = products;
    return route.queryParamMap;
  }))
      .subscribe(params => {
      this.category = params.get('category');
      this.filterProducts = (this.category) ?
      this.products.filter(p => (p.payload.val().category)===this.category) :
      this.products;
    });

Solution is simple >_< I lost my 2 hours for solve.解决方案很简单>_< 我浪费了 2 个小时来解决。 When we give queryParams by c.key - its value is like "bread" - with small letters, but our product.category value is with uppercase like "Bread" and so u must give value of category name - not category key Just change当我们通过 c.key 给 queryParams - 它的值就像“面包” - 带有小写字母,但我们的 product.category 值是大写的,如“面包”,所以你必须给出类别名称的值 - 而不是类别键只需更改

THIS:这个:

<a *ngFor="let c of categories$ | async" 
    routerLink="/"
    [queryParams]="{ category: c.key }"
    class="list-group-item list-group-item-action"
    [class.active] = 'category === c.key'
    >
    {{ c.payload.val().name }}
</a>

TO:至:

<a *ngFor="let c of categories$ | async" 
    routerLink="/"
    [queryParams]="{ category: c.payload.val().name }"
    class="list-group-item list-group-item-action"
    [class.active] = 'category === c.payload.val().name'
    >
    {{ c.payload.val().name }}
</a>

the correcte anser for the last version of angular is angular 最新版本的正确分析器是

products.component.ts: products.component.ts:

import { switchMap } from 'rxjs/operators';
import { Product } from './../models/product';
import { Categorie } from './../models/categorie';
import { ActivatedRoute } from '@angular/router';
import { ProductService } from './../product.service';
import { Component, OnInit } from '@angular/core';
import { CategoryService } from '../category.service';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.css']
})
export class ProductsComponent {

products: Product[]= [];
filteredProducts: Product[] = [];
categories$: Observable<any>;
category: string;
products$: Observable<any>;

  constructor(
    route:ActivatedRoute,
    productService:ProductService, 
    categoryService:CategoryService) {
   productService
   .getAll().pipe(
   switchMap(products=>{
     this.products = products;
     return route.queryParamMap;
   }))
   .subscribe(params =>{
     this.category =params.get('category');
     this.filteredProducts =(this.category)?
     this.products.filter(p=>p.category === this.category):
     this.products;
   });`enter code here`
this.categories$ = categoryService.getAll();

     }

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM