Angular 5 实现基于其他下拉框的级联下拉值绑定
Got it, let's tackle this cascading dropdown issue step by step. Here's how you can link your Category, Sub-Category, and Product Type dropdowns to filter options based on previous selections:
Step 1: Prepare Your Data Structure (Assumptions)
First, I'll assume your fetched categorys data includes nested sub-categories and product types (since you mentioned you already have this data). A typical structure might look like this:
interface Category { slug: string; name: string; subs: SubCategory[]; // Nested sub-categories under each category } interface SubCategory { slug: string; name: string; productTypes: ProductType[]; // Nested product types under each sub-category } interface ProductType { slug: string; name: string; }
If your data uses separate arrays (e.g., subs and productTypes are standalone with foreign keys like categorySlug), I'll note adjustments later.
Step 2: Update Component Class
Add variables to store filtered options, then subscribe to form control changes to update these lists:
import { Component, OnInit } from '@angular/core'; // ... other imports @Component({ // ... component metadata }) export class FormComponent implements OnInit { categorys: Category[] = []; filteredSubs: SubCategory[] = []; // Filtered sub-categories based on selected Category filteredProductTypes: ProductType[] = []; // Filtered product types based on selected Sub-Category error: any; // ... your existing product and productForm variables constructor(private categorySrv: CategoryService) {} // Adjust service name as needed ngOnInit() { this.fetchCategorys(); // Listen for Category selection changes this.productForm.controls['productCategory'].valueChanges.subscribe(categorySlug => { if (categorySlug) { // Find the selected category from the full list const selectedCategory = this.categorys.find(cat => cat.slug === categorySlug); if (selectedCategory) { this.filteredSubs = selectedCategory.subs; // Reset sub-category and product type selections this.productForm.controls['subCategory'].setValue(''); this.filteredProductTypes = []; } } else { // Clear filters if no category is selected this.filteredSubs = []; this.filteredProductTypes = []; } }); // Listen for Sub-Category selection changes this.productForm.controls['subCategory'].valueChanges.subscribe(subSlug => { if (subSlug) { // Get current selected category first const selectedCategory = this.categorys.find(cat => cat.slug === this.productForm.controls['productCategory'].value); if (selectedCategory) { // Find the selected sub-category const selectedSub = selectedCategory.subs.find(sub => sub.slug === subSlug); if (selectedSub) { this.filteredProductTypes = selectedSub.productTypes; // Reset product type selection this.productForm.controls['productType'].setValue(''); } } } else { // Clear product types if no sub-category is selected this.filteredProductTypes = []; } }); } fetchCategorys() { this.categorySrv.fetchCategories().then((response: any) => { this.categorys = response; console.log(this.categorys); }) .catch(error => this.error = error); } }
If Your Data Uses Separate Arrays:
If your subs and productTypes are standalone arrays (not nested in categories), adjust the filtering logic like this:
// For Sub-Category filter (if subs have a categorySlug field) this.filteredSubs = this.subs.filter(sub => sub.categorySlug === categorySlug); // For Product Type filter (if productTypes have a subCategorySlug field) this.filteredProductTypes = this.productTypes.filter(pt => pt.subCategorySlug === subSlug);
Step 3: Update Template
Modify your HTML to use the filtered lists, fix the require typo, add empty default options, and reorder dropdowns to match cascading flow:
<div class="form-group col-sm-6"> <label> Category</label> <select class="form-control" [(ngModel)]="product.productCategory" [formControl]="productForm.controls['productCategory']" required> <option value="">Select a Category</option> <option *ngFor="let item of categorys" [value]="item.slug">{{item.name}}</option> </select> </div> <div class="form-group col-md-6"> <label>Sub-Category</label> <select class="form-control" [(ngModel)]="product.subCategory" [formControl]="productForm.controls['subCategory']" required> <option value="">Select a Sub-Category</option> <option *ngFor="let item of filteredSubs" [value]="item.slug">{{item.name}}</option> </select> </div> <div class="form-group col-sm-6"> <label> Product Type</label> <select class="form-control" [(ngModel)]="product.productType" [formControl]="productForm.controls['productType']" required> <option value="">Select a Product Type</option> <option *ngFor="let item of filteredProductTypes" [value]="item.slug">{{item.name}}</option> </select> </div>
Key Changes:
- Replaced
subswithfilteredSubsandproductTypeswithfilteredProductTypesin the*ngForloops - Fixed
requiretorequired(correct HTML validation attribute) - Added empty default options to guide user selection
- Reordered dropdowns to follow Category → Sub-Category → Product Type flow (more intuitive for cascading)
That's it! Now when you select a Category, the Sub-Category dropdown will only show relevant options, and selecting a Sub-Category will filter the Product Type dropdown accordingly.
内容的提问来源于stack exchange,提问作者CE0

