Saya ingin membuat filter kotak centang, di mana saya memiliki daftar Tanaman dan Daftar Kabupaten.

Seperti yang Anda lihat di bawah ini:

enter image description here

Ingin yang saya inginkan sebenarnya seperti, Ketika saya menghapus centang pada BERAS di sebelah kanan saya harus menyembunyikan semua nama Distrik yang memiliki BERAS. Saya juga ingin menambahkan logika filter ke kotak centang Distrik seperti Ketika saya menghapus centang Thane, di sisi kanannya harus menyembunyikan kartu Beras yang hanya berisi Thane tidak semua Kartu Beras.

Saya mencoba logikanya, tetapi ketika saya mengedit array Object saya, itu menunjukkan Dua Kotak Centang. Saya tidak ingin dua Kotak Centang dengan nama yang sama. Biarkan saya menunjukkan kepada Anda hasil saya:

enter image description here

Di sini saya berbagi basis kode saya dengan kalian:

1. crop.model.ts

export class Crop {
    name: string;
    checked: boolean;
    district: string
    subCategory: Subcategory[];
}

export class Subcategory {
    id: number;
    name: string;
    checked: boolean;
}

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

3. crop.service.ts

import { Injectable } from "@angular/core";

import { Observable, of } from "rxjs";

import { Crop } from "../shared/crop.model";
import { CROPS } from "../shared/crop.data";

@Injectable({
  providedIn: "root"
})
export class CropService {
  constructor() { }

  crops: Crop[] = CROPS;

  getAllCrops(): Observable<Crop[]> {
    return of(this.crops);
  }

  getCrop(name: string): Observable<any> {
    const crop = this.crops.filter(crop => crop.name === name)[0];

    return of(crop);
  }
}

4. all-trades.component.html

<app-header></app-header>
<div
  fxLayout="row"
  fxLayout.lt-md="column"
  fxLayoutAlign="space-between start"
  fxLayoutAlign.lt-md="start stretch"
>
  <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 crop of crops$ | async">
              <mat-checkbox
                [checked]="crop.checked"
                (change)="onChange($event, i, crop)"
              >
                {{ crop.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 crop of crops$ | async">
              <mat-checkbox
                [checked]="crop.checked"
                (change)="onChange($event, i, crop)"
              >
                {{ crop.district }}
              </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 crops$ | 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>

<app-footer></app-footer>

5. all-trades.component.ts

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Crop } from 'src/app/shared/crop.model';
import { CropService } from '../crop.service';

@Component({
  selector: 'app-all-trades',
  templateUrl: './all-trades.component.html',
  styleUrls: ['./all-trades.component.css'],
})
export class AllTradesComponent implements OnInit {

  crops$: Observable<Crop[]>;

  constructor(private cropService: CropService) { }
  ngOnInit(): void {
    this.crops$ = this.cropService.getAllCrops();
  }
  onChange(event, index, item) {
    item.checked = !item.checked;
    console.log(index, event, item);
  }

}
-1
faisal moinuddin 19 November 2020, 17:49

1 menjawab

Jawaban Terbaik

Faisal.

Mungkin ini stackblitz akan membantu Anda masalah.

Saya pikir, adalah mungkin untuk memperbaiki masalah Anda tanpa menggunakan formulir. Saya telah membagi logika filter dan data menjadi yang dapat diamati. FilteredCrops$ baru yang dapat diamati akan menggabungkan data terbaru dari crop$, dan 2 subjek Perilaku dengan filter. Selain itu, array data tanaman akan difilter menggunakan fungsi yang mengembalikan nilai true, jika filter untuk nama dan distrik tanaman tertentu ini benar (yaitu dicentang).

1. app.component.ts

interface Filter {
  name: string;
  checked: boolean;
}

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  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))
        );
      })
    );
    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;
          })
        );
      })
    );
  }

  onNameFilterChange(item) {
    this.nameFilters$.value.find(
      filter => filter.name === item.name
    ).checked = !item.checked;
    this.nameFilters$.next([...this.nameFilters$.value]);
  }

  onDistrictFilterChange(item) {
    this.districtFilters$.value.find(
      filter => filter.name === item.name
    ).checked = !item.checked;
    this.districtFilters$.next([...this.districtFilters$.value]);
  }
}

2. Kerangka dari app.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>
1
Alexey Sapozhnikov 20 November 2020, 07:37