我正在使用Angular 11和Ionic作為我的UI庫。我遇到的問題是,我創建了一個 upsert 對話框組件,當我從控制臺手動獲取值時,編輯表單會回傳正確的值,但當我將一個現有物件傳遞給它時,所選專案卻沒有反映在 UI 中。
這是我的組件模板:
這是我的組件模板。
<ion-card>
<ion-card-header>/span>
<ion-card-title>{{title}}汽車座椅。汽車座椅</ion-card-title>
</ion-card-header>/span>
<ion-card-content>/span>
< form [formGroup]="form" (submit)="save()">
< app-input type="select" formControlName="CarSeatTypeId"/span> label="汽車座椅型別" [selectItems]="carSeatTypes" dataValue="CarSeatTypeId"/span> textValue="CarSeatTypeName"/span>> </app-input>>
<div Flex justifyContent="flex-end">/span>
<ion-button type="submit"> 保存</ion-button>
< ion-button type="button" color="light" (click)="close()" > 關閉</ion-button>
</div>/span>
</form>
</ion-card-content>
</ion-card>/span>
這是組件的型別腳本:
import { Component, Input, OnInit } from '@angular/core'。
import { FormBuilder, FormGroup, Validators } from '@angular/forms'。
import { ICarSeat } from './car-seats.interface'。
import { ICarSeatType } from '././core/interfaces/car-seat-type.interface'。
import { ModalController } from '@ionic/angular'/span>;
@Component({
templateUrl: './upsert-car-seat.component.html'。
})
export class UpsertCarSeatDialogComponent 實作OnInit {
@Input() carSeatTypes: ICarSeatType[] = [] 。
@Input() existing: ICarSeat;
form: FormGroup;
get title(): string {
return (!this.existing ? 'Create' : 'Edit')。)
}
constructor(private formBuilder: FormBuilder,
私有modalController。ModalController) { }
ngOnInit()。void {
this.form = this.buildForm()。
}
close()。void {
this.modalController.dismiss()。
}
save()。void {
if (this.form.invalid) {
Object.keys(this.form。 controls).forEach(key => {
this.form.get(key)。 setValue(this.form.get(key).value)。
});
return;
}
this.modalController。 dismiss(this.form.value) 。
}
private buildForm()。FormGroup {
return this.formBuilder.group({
CarSeatTypeId: [this.existing? .CarSeatTypeId, Validators.required] 。
});
}
這是我打開對話框的方法:
這是我打開對話框的方法。
async edit(carSeat: ICarSeat)。Promise<void> {
const modal = await this.modalController.create({
component: UpsertCarSeatDialogComponent,
componentProps: {
carSeatTypes: this.carSeatTypes。
existing: carSeat
}
});
modal.onWillDismiss().then(results => {
if (results?.data) {
carSeat.CarSeatTypeId = result.data.CarSeatTypeId;
this.carSeatsService.updateCarSeat(carSeat)。 subscribe(result => {
this.alertService.showConfirmation({
header: 'Car Seat Updated',
message: `The ${carSeat.CarSeatTypeName}已被更新。`。
buttons: [
{ text: 'Close' }
]
});
});
}
});
modal.present()。
而這是app-input模板(它最終被轉換為ion-select):
<!-- dropdown -->
<ng-container *ngIf=" elementType =='ion-select'">
<ion-item>
<ion-label position="stacked"/span>> {{label}}</ion-label>>
<ion-select [(ngModel)]="value"/span>
[cancelText]="cancelText"。
[compareWith]="compareWith"。
[disabled]="disabled"。
[interface]="interface"。
[interfaceOptions]="interfaceOptions"。
[mode]="mode"。
[multiple]="multiple"。
[name]="name"。
[okText]="okText"。
[placeholder]="placeholder"。
[selectedText]="selectedText"。
[value]="value">/span>
< ion-select-option *ngFor="let item of selectItems" value="{item[dataValue]}}" > {{item[textValue]}}</ion-select-option>。
</ion-select>/span>
<ion-text *ngIf="ngControl?.control?.errors && ngControl?
style="font-size:small;"。
color="danger"。
[innerHTML]="validationMessage">/span></ion-text>
</ion-item>/span>
</ng-container>/span>
。
我有點不知所措,不知道該怎么做。我試著將構建表單移到建構式中,然后再移到 OnAfterViewInit 中,我試著通過呼叫 changeDetectionRef.detectChanges() 來手動更新 UI,我還試著在 this.buildForm() 之后呼叫 this.form.get('CarSeatTypeId').setValue(this.existing?.CarSeatTypeId) 但所有這些似乎都不重要。
從截圖來看,該表單顯然有一個值,而且它正在參考一個現有的 CarSeatType。希望得到任何幫助。
Update
我還嘗試使用 setTimeout,將超時設定為 3,000ms 來手動設定控制值。這也不起作用。
uj5u.com熱心網友回復:
聽起來像是一個變化檢測問題。你是否可能在突變一個物件?Angular變化檢測不喜歡突變,你應該不惜一切代價避免突變,以確保變化檢測的作業(即確保值的變化正確反映在UI中)。
當一個物件被突變時,物件的參考不會改變。下面是一個突變的例子:
const obj = {a:2}
obj.a = 3 // 變異警告,這是不好的。
為了避免這種情況,有很多方法。這里有幾個簡單的方法:
let obj = {a:2}。
obj = {a:3} // 這里沒有突變,我們只是在創建一個新的物件。
從'lodash-es'匯入{cloneDeep}。
讓obj = {a:2}
obj.a = 3 // 變異警告,這很糟糕。
obj = cloneDeep(obj) //通過創建一個新的物件(因此也是一個新的物件參考,這將導致Angular變化檢測的啟動)來解決變異問題。
當處理物件突變時,我通常依賴lodash cloneDeep,因為它使用起來很簡單。但也有許多其他的方法來解決這個問題。
注意當使用.push().unshift()等時,突變也可能發生在陣列上。同樣,只需克隆陣列就可以解決這個問題。
這可能不是一個好問題。
這可能不是你的問題,但當你面臨變化檢測問題時,總是值得確保這不是問題。
看看你的代碼,有很多超長的代碼,很難確定問題出在哪里,但也許可以從以下幾個方面入手:
.setValue(cloneDeep(this.form.get(key).value))
無論你在哪里使用setValue
。uj5u.com熱心網友回復:
潛在的問題與我們為ion-select使用的包裝器有關,一位同事做了以下的修改,解決了我的問題:
< ng-container *ngIf=" elementType =='ion-select'">
<ion-item>
<ion-label position="stacked"/span>>
< ion-text *ngIf="labelPrefix" [color]=" labelPrefixColor"> {{labelPrefix}}</ion-text>>。
{{label}}
</ion-label>{label}}。
<ion-select [(ngModel)]="value"/span>
[cancelText]="cancelText"。
[compareWith]="compareWith"。
[disabled]="disabled"。
[interface]="interface"。
[interfaceOptions]="interfaceOptions"。
[mode]="mode"。
[multiple]="multiple"。
[name]="name"。
[okText]="okText"。
[placeholder]="placeholder"。
[value]="value">/span>
< ion-select-option *ngFor="let item of selectItems" value="{item[dataValue]}}" > {{item[textValue]}}</ion-select-option>。
</ion-select>/span>
<ion-text *ngIf="ngControl?.control?.errors && ngControl?
style="font-size:small;"。
color="danger"。
[innerHTML]="validationMessage">/span></ion-text>
</ion-item>/span>
</ng-container>/span>
而且
compareWith: ((currentValue: any, compareValue: any) => boolean) | null | string | undefined = (currentValue: any, compareValue: any) => {
return currentValue[this. dataValue] === compareValue[this.dataValue] 。
};
具體來說,新舊版本的區別在于增加了compareWith系結,洗掉了selectedValue系結。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/330244.html
標籤:

