问题
I tried but, I guess I coded exactly opposite that what I wanted.
1. all-trades.component.html
<div
fxLayout="row"
fxLayout.lt-md="column"
fxLayoutAlign="space-between start"
fxLayoutAlign.lt-md="start stretch"
*ngIf="crops$ | async"
>
<div class="container-outer" fxFlex="20">
<div class="filters">
<section class="example-section">
<span class="example-list-section">
<h1>Select Crop</h1>
</span>
<span class="example-list-section">
<ul>
<li *ngFor="let filter of nameFilters$ | async">
<mat-checkbox
[checked]="filter.checked"
(change)="onNameFilterChange(filter)"
>
{{ filter.name }}
</mat-checkbox>
</li>
</ul>
</span>
</section>
<section class="example-section">
<span class="example-list-section">
<h1>Select District</h1>
</span>
<span class="example-list-section">
<ul>
<li *ngFor="let filter of filteredDistrictCheckboxes$ | async">
<mat-checkbox
[checked]="filter.checked"
(change)="onDistrictFilterChange(filter)"
>
{{ filter.name }}
</mat-checkbox>
</li>
</ul>
</span>
</section>
</div>
</div>
<div class="content container-outer" fxFlex="80">
<mat-card
class="crop-card"
style="min-width: 17%"
*ngFor="let crop of filteredCrops$ | async"
[hidden]="!crop.checked"
>
<a [routerLink]="[crop.name]">
<mat-card-header>
<img
mat-card-avatar
class="example-header-image"
src="/assets/icons/crops/{{ crop.name }}.PNG"
alt="crop-image"
/>
<mat-card-title>{{ crop.name }}</mat-card-title>
<mat-card-subtitle>100 Kgs</mat-card-subtitle>
</mat-card-header>
</a>
<mat-card-content>
<p>PRICE</p>
</mat-card-content>
<mat-card-content>
<p>{{ crop.district }}</p>
</mat-card-content>
</mat-card>
</div>
</div>
2.all-trades.component.ts
import { OnInit } from '@angular/core';
import { Component } from "@angular/core";
import { BehaviorSubject, combineLatest, Observable } from "rxjs";
import { map, shareReplay, switchMap, tap } from "rxjs/operators";
import { Crop } from 'src/app/shared/crop.model';
import { CropService } from '../crop.service';
// dialog box
interface Filter {
name: string;
checked: boolean;
}
@Component({
selector: 'app-all-trades',
templateUrl: './all-trades.component.html',
styleUrls: ['./all-trades.component.css'],
})
export class AllTradesComponent implements OnInit {
crops$: Observable<Crop[]>;
filteredCrops$: Observable<Crop[]>;
nameFilters$ = new BehaviorSubject<Filter[]>([]);
districtFilters$ = new BehaviorSubject<Filter[]>([]);
filteredDistrictCheckboxes$: Observable<Filter[]>;
constructor(private cropService: CropService) { }
ngOnInit(): void {
this.crops$ = this.cropService.getAllCrops().pipe(
tap(crops => {
const names = Array.from(new Set(crops.map(crop => crop.name)));
this.nameFilters$.next(
names.map(name => ({ name, checked: true } as Filter))
);
const dictricts = Array.from(new Set(crops.map(crop => crop.district)));
this.districtFilters$.next(
dictricts.map(name => ({ name, checked: true } as Filter))
);
}),
shareReplay(1)
);
this.filteredCrops$ = combineLatest(
this.crops$,
this.nameFilters$,
this.districtFilters$
).pipe(
map(
([crops, nameFilters, districtFilters]: [
Crop[],
Filter[],
Filter[]
]) => {
let items = [...crops];
items = items.filter(item => {
const associatedNameFilter = nameFilters.find(
filter => filter.name === item.name
);
const associatedDistrictFilter = districtFilters.find(
filter => filter.name === item.district
);
return (
associatedNameFilter.checked && associatedDistrictFilter.checked
);
});
return items;
}
)
);
this.filteredDistrictCheckboxes$ = this.nameFilters$.pipe(
switchMap((nameFilters: Filter[]) => {
return this.crops$.pipe(
map(crops => {
const enabledNames = nameFilters
.filter(item => item.checked)
.map(filter => filter.name);
const enabledDistricts = Array.from(
new Set(
crops
.filter(crop => enabledNames.includes(crop.name))
.map(crop => crop.district)
)
);
const result = this.districtFilters$.value.filter(item =>
enabledDistricts.includes(item.name)
);
return result;
})
);
})
);
}
onChange(event, index, item) {
item.checked = !item.checked;
console.log(index, event, item);
}
3. crop.data.ts
import { Crop } from "./crop.model";
export const CROPS: Crop[] = [
{
name: "Rice", // I want this Rice
checked: true,
district: "Thane",
subCategory: [
{
id: 1,
name: "Basmati",
checked: true
},
{
id: 2,
name: "Ammamore",
checked: true
}
]
},
{
name: "Rice", // also this one but on clicking on single Checkbox with name as Rice
checked: true,
district: "Nashik",
subCategory: [
{
id: 1,
name: "Basmati",
checked: true
},
{
id: 2,
name: "Ammamore",
checked: true
}
]
},
{
name: "Wheat",
checked: true,
district: "Nashik",
subCategory: [
{
id: 1,
name: "Durum",
checked: true
},
{
id: 2,
name: "Emmer",
checked: true
}
]
},
{
name: "Barley",
checked: true,
district: "Ratnagiri",
subCategory: [
{
id: 1,
name: "Hulless Barley",
checked: true
},
{
id: 2,
name: "Barley Flakes",
checked: true
}
]
},
{
name: "Barley",
checked: true,
district: "Thane",
subCategory: [
{
id: 1,
name: "Hulless Barley",
checked: true
},
{
id: 2,
name: "Barley Flakes",
checked: true
}
]
}
];
4. crop.model.ts
export class Crop {
name: string;
checked: boolean;
district: string
subCategory: Subcategory[];
}
export class Subcategory {
id: number;
name: string;
checked: boolean;
}
Here I am sharing my output result
enter image description here
I want output like this
enter image description here
As you can see on left hand side there is filter, when someone check that checkboxes the result display according to that. But in my scenario all the checkbox is selected by default. i want to make it working excatly like e-commerece filter. Please share code on stackblitz
来源:https://stackoverflow.com/questions/64981058/i-want-to-make-an-e-commerce-filter-by-category-in-angular