如何在Angular 6中实现类似JSTL循环表单并获取数组数据?
Got it, let's convert that JSTL/jQuery setup to Angular 6 smoothly. Here's a step-by-step implementation that mirrors your original functionality, using Angular's native form handling instead of jQuery:
1. Component Class (e.g., app.component.ts)
First, we'll define our data structures and initialize values in the component. This replaces the JSTL variables and handles data sync automatically via Angular's two-way binding:
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { // Replace these with your actual values (or fetch from a service) amountOfDayEnds = 5; clientTypes = ['Retail', 'Corporate', 'VIP']; // Initialize a 2D array to store input values: [day][clientType] = value daysData: number[][] = Array(this.amountOfDayEnds) .fill(0) .map(() => Array(this.clientTypes.length).fill(0)); // Handle form submission onSubmit() { // Directly access the synced data from daysData console.log('Raw form data:', this.daysData); // If you need a jQuery-style serialized format (key-value pairs), convert it: const serializedData: {name: string, value: number}[] = []; this.daysData.forEach((dayValues, dayIndex) => { dayValues.forEach((value, typeIndex) => { serializedData.push({ name: `dataClients[${dayIndex}][${typeIndex}]`, value: value }); }); }); console.log('Serialized (jQuery-like):', serializedData); // Add your API call here to send data to the backend (use Angular's HttpClient) } }
2. Template File (e.g., app.component.html)
We'll use Angular's *ngFor to replicate the JSTL loops, add two-way binding with ngModel, and include validation matching your original rules:
<form #clientForm="ngForm" (ngSubmit)="onSubmit()"> <table> <tbody> <!-- Loop through each day --> <tr class="text-center hover-table" *ngFor="let dayData of daysData; let dayIndex = index"> <td>{{ dayIndex + 1 }}</td> <!-- Display 1-based day count --> <!-- Loop through each client type for the current day --> <td *ngFor="let value of dayData; let typeIndex = index"> <div> <input class="text-center field" type="number" [(ngModel)]="daysData[dayIndex][typeIndex]" name="data-{{dayIndex}}-{{typeIndex}}" <!-- Unique name required for template-driven forms --> min="0" required pattern="^\d+$" <!-- Enforce integer values --> #clientInput="ngModel" > <!-- Validation error messages (mirror your original validation rules) --> <div *ngIf="clientInput.invalid && (clientInput.dirty || clientInput.touched)" class="error-text"> <small *ngIf="clientInput.errors?.required">This field is required.</small> <small *ngIf="clientInput.errors?.min">Value must be ≥ 0.</small> <small *ngIf="clientInput.errors?.pattern">Only integer numbers are allowed.</small> </div> </div> </td> </tr> </tbody> </table> <!-- Submit button disabled if form is invalid --> <button type="submit" [disabled]="clientForm.invalid">Submit</button> </form>
Key Notes:
- No jQuery Needed: Angular's two-way binding (
[(ngModel)]) keeps the component'sdaysDataarray in sync with input values automatically—no need forserialize(). - Validation: We've replicated your original validation rules (≥0, integers, required) using Angular's native form validators, with clear error messages.
- Dynamic Loops:
*ngForreplaces JSTL's<c:forEach>—dayIndex + 1matches your originalday.countfor 1-based numbering. - Form Submission: When you submit,
this.daysDatacontains all input values. If you need the exact key-value format from jQuery'sserialize(), we've included a conversion example.
If you're working with more complex forms later, you might want to explore Angular's Reactive Forms (using FormArray), but this template-driven approach is perfect for matching your original JSTL setup.
内容的提问来源于stack exchange,提问作者user9804931

