Angular动态展开复选框列表实现与API交互技术咨询
Hey there! Since you're new to Angular and TypeScript, let's walk through solving your two questions step by step—grouping your API data by categoryId for the expansion panels, then collecting the selected checkbox values to send back to the API.
categoryId and Rendering the Dynamic List First, we'll transform the raw API response into a grouped structure that’s easy to iterate over in your template. Let’s start with TypeScript interfaces to define our data shapes (this helps catch errors early!):
// Define the shape of a single access item from the API interface AccessItem { categoryId: string; accessId: string; catAccessStatus: string; BoRefCategory: { categoryId: string; categoryDesc: string }; BoRefAccess: { accessId: string; accessDesc: string }; isChecked?: boolean; // We'll add this to track checkbox state } // Define the grouped structure: key = categoryId, value = category details + items interface GroupedAccess { [categoryId: string]: { categoryDesc: string; items: AccessItem[]; }; }
Next, process the API response to group items by categoryId (we’ll also deduplicate items since your sample data has duplicates):
import { HttpClient } from '@angular/common/http'; import { Component } from '@angular/core'; @Component({ selector: 'app-access-panel', templateUrl: './access-panel.component.html' }) export class AccessPanelComponent { groupedAccess: GroupedAccess = {}; constructor(private http: HttpClient) { this.fetchAccessData(); } fetchAccessData(): void { this.http.get<{ code: string; message: string; data: AccessItem[] }>('your-api-endpoint-url') .subscribe(response => { this.groupedAccess = response.data.reduce((acc, item) => { const categoryId = item.categoryId; // Initialize the group if it doesn't exist if (!acc[categoryId]) { acc[categoryId] = { categoryDesc: item.BoRefCategory.categoryDesc, items: [] }; } // Avoid duplicate access items const isDuplicate = acc[categoryId].items.some(existing => existing.accessId === item.accessId); if (!isDuplicate) { acc[categoryId].items.push({ ...item, isChecked: false }); // Initialize checkbox state } return acc; }, {} as GroupedAccess); }); } }
Now render the grouped data with expansion panels (we’ll use Angular Material’s components here, but you can adapt this to plain HTML if needed):
<!-- Make sure you've imported Angular Material modules (MatAccordionModule, MatCheckboxModule, etc.) in your module --> <mat-accordion> <!-- Iterate over each grouped category --> <mat-expansion-panel *ngFor="let group of groupedAccess | keyvalue"> <mat-expansion-panel-header> <mat-panel-title>{{ group.value.categoryDesc }}</mat-panel-title> </mat-expansion-panel-header> <!-- Render checkboxes for each access item in the group --> <div class="checkbox-list" *ngFor="let item of group.value.items"> <mat-checkbox [(ngModel)]="item.isChecked" [value]="item.accessId"> {{ item.BoRefAccess.accessDesc }} </mat-checkbox> </div> </mat-expansion-panel> </mat-accordion>
Don’t forget to import FormsModule in your Angular module to use [(ngModel)] for two-way binding!
Add a method to collect all selected checkbox values, then send them to your API:
onSubmitSelections(): void { // Collect all selected access items (adjust the shape based on your API's needs) const selectedItems = Object.values(this.groupedAccess) .flatMap(group => group.items.filter(item => item.isChecked).map(item => ({ categoryId: item.categoryId, accessId: item.accessId })) ); // Send the data to your API this.http.post('your-submit-endpoint-url', { selectedItems }) .subscribe({ next: (response) => { console.log('Selections submitted successfully!', response); // Add success feedback here (e.g., toast message) }, error: (error) => { console.error('Error submitting selections:', error); // Add error handling here } }); }
Add a submit button to your template to trigger this method:
<button mat-raised-button color="primary" (click)="onSubmitSelections()" style="margin-top: 1rem;"> Submit Selections </button>
Quick Notes:
- Ensure
HttpClientModuleis imported in your root module to use Angular’s HTTP client. - If you’re not using Angular Material, replace the
<mat-*>components with plain HTML elements (e.g.,<details>for expansion panels,<input type="checkbox">for checkboxes)—the binding logic stays the same. - Adjust the shape of the data sent to the API to match what your backend expects.
内容的提问来源于stack exchange,提问作者kiki

