提问人:laurarana 提问时间:5/24/2023 更新时间:5/24/2023 访问量:19
如何在formArray中正确设置mat-checkbox值,从API读取保存的数据并为新的formArray元素设置默认值(false)?
How to correctly set mat-checkbox values in formArray, reading saved data from API and having default value (false) for new formArray elements?
问:
我正在研究垫子踏步结构,以创建实体“租赁合同”。我可以从零开始创建一个新的租赁合同,或者打开保存的草稿并继续填充数据并将其保存到数据库 usinn 实体框架 API 中。
一份租赁合同可以指客户在合同有效期内使用的n辆车。
每辆车都用一个 formArray 元素表示。每辆车可以由出租房屋拥有,也可以转租,并有许多属性由用户填充。除了复选框之外,几乎所有这些属性都运行良好。
我创建了一个垫子复选框来显示所选机器是否被转租。我需要三种不同的行为:
- 当我为 formArray 创建一个空元素时,我需要将“false”值设置为复选框。
- 用户选择机器代码后,系统会检查它是否已转租,并将复选框选择设置为“true”(否则为“false”)。
- 如果我从草稿加载数据,则需要根据我之前保存在数据库中的内容来设置复选框。
如果我使用 formControl 名称,我将无法管理来自 API 的值。 如果我使用 ngModel,我可以从 DB 中读取,但是当我向其中添加新元素时,formArray 无法正常工作。
我需要的是了解如何配置我的formArray元素,以便开始所有需要的行为。
我的表格如下所示:
这是我的“混合”代码(我尝试了几次更改并注释了一些不起作用的代码):
component.ts:
[...]
vehiclesForm = new FormGroup({
stocks: new FormArray([])
});
[...]
ngOnInit(): void {
this.vehiclesForm = this.formBuilder.group({
stocks: this.formBuilder.array([])
});
}
loadData(contractData: any) {
this.contractData = contractData;
//console.log('contract-vehicles - contractData', contractData);
this.getAllBuildingSitesByCustomerId(contractData.customerId);
this.rentalTypeId = contractData.rentalTypeId;
this.secondRentalTypeId = contractData.secondRentalTypeId;
//console.log("this.contractData.rentalStocks", this.contractData.rentalStocks);
if ((<FormArray>this.vehiclesForm.get("stocks")).length === 0) {
if (this.contractData.rentalStocks != null && this.contractData.rentalStocks?.length > 0) {
this.getRentalStocksDetail(this.contractData.rentalStocks).subscribe(
(stockResults) => {
this.contractData.rentalStocks.forEach((rentalStock, index) => {
const stock = stockResults[index];
const stockIdControl = new FormControl(stock, autocompleteObjectValidator());
this.filteredStocks[index] = stockIdControl.valueChanges.pipe(
debounceTime(300),
switchMap((value) => this.getStocks(value, index))
);
this.addStockToFormArray(rentalStock, stockIdControl);
this.onStockSelectionChange(stock, index);
});
},
(err) => {
console.log("contract-vehicles.component: getRentalStocksDetail:", err);
},
);
} else {
this.addNewStockToFormArray();
}
}
}
getRentalStocksDetail(stocks: any[]): Observable<any[]> {
let calls = [];
stocks.forEach(stock => { calls.push(this.stockService.getStock(stock.stockId, true)); });
return forkJoin(calls);
}
getControls() {
//console.log("<FormArray>this.vehiclesForm.get('stocks')).controls",(<FormArray>this.vehiclesForm.get("stocks")).controls);
return (<FormArray>this.vehiclesForm['controls'].stocks['controls']);
}
getStocks(filter: any, index: number): Observable<any[]> {
if (filter?.length < 2 || typeof filter !== 'string') {
return of([]);
}
this.queryStock.find = filter;
this.queryStock.startDate = moment(((<FormGroup>(<FormArray>this.vehiclesForm.get("stocks")).controls[index])).controls.startDate.value).format('YYYY-MM-DDT00:00:00');
this.queryStock.endDate = moment(((<FormGroup>(<FormArray>this.vehiclesForm.get("stocks")).controls[index])).controls.endDate.value).format('YYYY-MM-DDT23:59:59');
return this.rentalStockService.getAvailableRentalStocks(this.queryStock).pipe(
map((response) => response),
tap((response: any[]) => {
return response.sort((a, b) => {
if (a.ownerRef === b.ownerRef) {
return a.registrationNumber < b.registrationNumber ? -1 : 1
} else {
return a.ownerRef < b.ownerRef ? -1 : 1
}
});
})
);
}
displayStock(stock: any): string {
var desc: string;
if (stock && stock.id) {
desc = stock.registrationNumber;
//console.log("stock.ownerRef", stock.ownerRef);
if (stock.ownerRef) {
desc = stock.ownerRef + ' - ' + desc;
}
}
return desc;
}
addNewStockToFormArray() {
if (!(<FormArray>this.vehiclesForm.get('stocks')).valid) {
return;
}
const formLength = (<FormArray>this.vehiclesForm.get('stocks')).length;
const stockIdControl = new FormControl(null, autocompleteObjectValidator());
this.filteredStocks[formLength] = stockIdControl.valueChanges.pipe(
debounceTime(300),
switchMap((value) => this.getStocks(value, formLength))
);
this.addStockToFormArray(null, stockIdControl);
}
public addStockToFormArray(rentalStock: any, stockControl: FormControl) {
console.log("rentalStock", rentalStock);
console.log("subleased", rentalStock?.subleased);
const checkDefaultValues = <FormGroup>(<FormArray>this.vehiclesForm.get("stocks")).controls[0];
(<FormArray>this.vehiclesForm.get("stocks")).push(
new FormGroup({
stockId: new FormControl(rentalStock ? rentalStock.id : 0),
startDate: new FormControl(rentalStock?.startDate ?? this.contractData.startDate),
endDate: new FormControl(rentalStock?.endDate ?? this.contractData.expiryDate),
stock: stockControl,
//subleased: new FormControl({value: rentalStock ? rentalStock.subleased : false, disabled: true}),
})
);
}
onStockSelectionChange(myStock: any, j: number, fromUI: boolean = false) {
console.log("onStockSelectionChange", fromUI);
let formArray = (<FormArray>this.vehiclesForm.get("stocks")).controls;
formArray[j].get('stockId').setValue(myStock.id);
//formArray[j].get('subleased').setValue(myStock.subleased);
if (fromUI) {
this.contractData.rentalStocks[j].subleased = myStock.subleased;
}
}
HTML格式:
<form [formGroup]="vehiclesForm">
<table style="width: 50%;">
<thead>
<tr>
<th style="text-align: center;">{{'StartDate' | translate}}</th>
<th style="text-align: center;">{{'EndDate' | translate}}</th>
<th style="text-align: center;">{{'Stock' | translate}}</th>
<th style="text-align: center;">{{'Subleased' | translate}}</th>
<th style="text-align: center;">{{'Delete' | translate}}</th>
</tr>
</thead>
<tbody formArrayName="stocks">
<tr *ngFor="let stock of getControls(); let i = index" [formGroupName]="i">
<!-- Start Date -->
<td style="text-align: center;">
<div class="hidden">
<input type="text" class="form-control" formControlName="stockId">
</div>
<mat-form-field appearance="outline" class="field-width-120 w-100-p mb-12">
<mat-label></mat-label>
<input matInput [matDatepicker]="startDatePicker"
formControlName="startDate"
[min]="contractData.startDate" [max]="contractData.expiryDate">
<mat-datepicker-toggle matSuffix [for]="startDatePicker">
</mat-datepicker-toggle>
<mat-datepicker #startDatePicker></mat-datepicker>
</mat-form-field>
</td>
<!-- End Date -->
<td style="text-align: center;">
<mat-form-field appearance="outline" class="field-width-120 w-100-p mb-12">
<mat-label></mat-label>
<input matInput [matDatepicker]="endDatePicker"
formControlName="endDate"
[min]="contractData.startDate" [max]="contractData.expiryDate">
<mat-datepicker-toggle matSuffix [for]="endDatePicker">
</mat-datepicker-toggle>
<mat-datepicker #endDatePicker></mat-datepicker>
</mat-form-field>
</td>
<!-- Stock -->
<td style="text-align: center;">
<mat-form-field appearance="outline" class="field-width-stock w-100-p mb-12">
<mat-label></mat-label>
<input matInput formControlName="stock" [value]="stock"
[matAutocomplete]="autoStock" type="text" autocomplete="off">
<mat-autocomplete #autoStock="matAutocomplete" [displayWith]="displayStock">
<mat-option *ngFor="let myStock of filteredStocks[i] | async"
[value]="myStock" (onSelectionChange)="onStockSelectionChange(myStock, i, true)">
{{displayStock(myStock)}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</td>
<!-- Subleased -->
<td style="vertical-align: initial; text-align: center;">
<mat-checkbox class="h5" [ngModel]="contractData.rentalStocks[i]?.subleased" [ngModelOptions]="{standalone: true}" disabled></mat-checkbox>
</td>
<!-- Delete -->
<td style="vertical-align: initial; text-align: center;">
<button mat-icon-button color="warn"
(click)="onDeleteItem(i); $event.preventDefault()">
<mat-icon>delete</mat-icon>
</button>
</td>
</tr>
<tr>
<button mat-raised-button class="header-button mt-24 mt-md-0"
(click)="addNewStockToFormArray(); $event.preventDefault()">
<mat-icon>add</mat-icon>
</button>
</tr>
</tbody>
</table>
</form>
任何建议/帮助将不胜感激!
非常感谢和最诚挚的问候,
劳 拉
答: 暂无答案
评论