Meine Bildungserfahrung ist wie folgt:
<cdk-virtual-scroll-viewport itemSize="5" class="list-scroll"> <app-education-item *ngFor="let education of loadedEducations" (isSelected)="changeSelected(education)" [ngClass]="{ selected: education == loadedEducation }" [education]="education" (isRemoved)="removeEducation(education)" ></app-education-item> </cdk-virtual-scroll-viewport>
und sind die folgenden Komponenten
<div [ngClass]="{ 'list-item-container-collapsed' : isCollapsed, 'list-item-container': !isCollapsed, 'unselected': !isActive, 'selected': isActive}" (click)="selectEducation()"> <div class="top-items-container" style="display: flex;"> <div class="item-text"> <span class="txt-header">{{educationHeader}}</span> <p class="txt-date"> <span>{{startDate}}</span> - <span>{{endDate}}</span> </p> </div> </div>
Verfügt über die folgende Logik zum Anzeigen von aus Parametern erhaltenen Daten:
export class EducationItemComponent implements OnInit { @Input() education: Education; isCollapsed = false; isActive = false; startDate: string; endDate: string; educationHeader: string; educationDescription: string; constructor() { } ngOnInit(): void { console.log(this.education); this.startDate = this.education.startDate != '' ? formatDate(this.education.startDate, 'MMM yyyy', 'en-US') : formatDate(new Date(), 'MM YYYY', 'en-US') ; this.endDate = this.education.endDate != 'present' ? this.endDate = formatDate(this.education.endDate, 'MMM yyyy', 'en-US') : this.education.endDate; this.educationHeader = this.education.degree == undefined || this.education.description == undefined ? '' : this.education.degree + ' at ' + this.education.school; if (!this.education.description.enUS && this.education.description.nlNL) { this.educationDescription = this.education.description.nlNL; } else if (this.education.description.enUS) { this.educationDescription = this.education.description.enUS; } }
Ich verwende benutzerdefinierte Ereignisse, um Updates zu verarbeiten
@Output() updatedValue: EventEmitter<any> = new EventEmitter<string>(); constructor() {} ngOnInit(): void {} fieldChanged(changes: SimpleChanges) { this.updatedValue.emit(changes); }
Dann habe ich das folgende HTML zum Bearbeiten der Daten:
<div class="update-wrap"> <div class="list-header">Update education</div> <div> <div class="col-sm-6 input-wrapper"> <app-input-field label="Institution" [value]="loadedEducation.school" (updatedValue)="loadedEducation.school = $event" ></app-input-field> </div> <div class="col-sm-6 input-wrapper date-picker-input"> <app-input-field label="Degree" [value]="loadedEducation.degree" (updatedValue)="loadedEducation.degree = $event" ></app-input-field> </div> </div> </div>
Die aktualisierten Daten im Feld [value]="loadedEducation.school" (updatedValue)="loadedEducation.school = $event"
werden jedoch nicht an die untergeordnete Komponente gebunden, sodass nichts angezeigt wird, bis sie aktualisiert wird und die Daten aus der Datenbank abruft.
Welche Möglichkeiten kann ich versuchen umzusetzen?
Ich habe versucht, ngOnChanges zu implementieren, aber ohne Erfolg.
当您更改列表中项目的属性时,loadedEducations 列表不会更改。尝试刷新列表(
this.loadedEducations = returnedEducations
)或在项目中使用状态管理问题的根本原因是
@Input()
无法检测到对象和数组内部的更改,因为它们都是 引用类型。您的education
属性是一个对象,因此在父组件中进行的直接改变属性的更改(例如education.school = 'newValue'
)不会触发子组件的属性@Input() education
的任何更改有几种方法可以解决这个问题,每种方法都有其优点和缺点:
仅传递您需要的属性作为基元
parent.component.ts
parent.component.html
child.component.ts
优点:
缺点:
@Input
数量的增长,变得笨重Education
接口)绑定更改时在父级中重建对象
parent.component.ts
深度克隆
parent.component.html
child.component.ts
优点:
Education
接口,保持父组件和子组件之间的语义耦合缺点:
updateEducation()
函数将反应性元素传递到您的子组件中,例如
BehaviorSubject
,并直接订阅更改parent.component.ts
parent.component.html
child.component.ts
child.component.html
优点:
educationSubject
放入服务中,并将相同的服务注入到任何需要它的组件中缺点:
updateEducation()
函数| async
)等