Angular Material实现FormArray输入项按4列每行展示
Looking at your code, the problem is that you're rendering all 16 FormArray controls as individual rows, which stacks them vertically (giving the impression they're all in one column). To fix this, we need to group the 16 controls into 4 columns (each containing 4 inputs) and adjust the HTML layout accordingly.
Step 1: Add a Getter to Group FormArray Controls into Columns
First, add a getter in your component to split the FormArray's controls into 4 columns (each with 4 items):
get destColumns(): FormGroup[][] { const destControls = (this.combinationForm.get('dest') as FormArray).controls as FormGroup[]; const columnCount = 4; // Since you have 4 regions const columns: FormGroup[][] = []; // Split the 16 controls into 4 columns of 4 for (let i = 0; i < columnCount; i++) { const startIndex = i * columnCount; columns.push(destControls.slice(startIndex, startIndex + columnCount)); } return columns; }
Step 2: Rewrite the HTML Layout
Update your template to render the grouped columns instead of individual controls. We'll use a horizontal flex container for the columns, and each column will hold 4 vertical input fields:
<div *ngIf="enableCombinationDirective"> <div class="h1">Add Prices</div> <div [formGroup]="combinationForm"> <!-- Horizontal container for 4 columns --> <div fxLayout="row" fxLayoutAlign="space-between stretch" style="gap: 16px;"> <!-- Loop through each column --> <div fxFlex="25%" *ngFor="let column of destColumns; let colIndex = index"> <!-- Loop through the 4 items in the column --> <div *ngFor="let item of column; let rowIndex = index" [formGroupName]="colIndex * 4 + rowIndex" style="margin-bottom: 16px;" > <mat-form-field appearance="outline" style="width: 100%;"> <mat-label>{{ item.get('combinationTitle').value }}</mat-label> <input matInput type="number" formControlName="price" placeholder="Enter Price" /> <mat-checkbox formControlName="isActive" matSuffix></mat-checkbox> </mat-form-field> </div> </div> </div> <div fxLayout="row" style="margin-top: 24px;"> <button fxFlex="100" mat-raised-button color="primary" (click)="save()"> Save Changes </button> </div> </div> </div>
Key Fixes Explained:
- Column Grouping: The
destColumnsgetter splits your 16 FormArray controls into 4 logical columns, matching your 4-region requirement. - Horizontal Layout: The outer
fxLayout="row"container arranges the 4 columns side-by-side, withfxFlex="25%"ensuring each column takes equal width. - Correct Form Group Index: We calculate the correct
formGroupNameusingcolIndex * 4 + rowIndexto map back to the original FormArray indices (0-15). - Cleaner Structure: Removed unnecessary nested flex containers and adjusted spacing to make the layout consistent.
Optional Cleanup Note
I noticed your getRegionsCombinations function declares a selectedRegion variable that isn't used later. You can safely remove that line to clean up your code:
// Remove this unused line: // let selectedRegion: IRegion[] = this.regions.filter((data) => data.id === region);
内容的提问来源于stack exchange,提问作者Ehsan Nissar

