Angular 13父子组件数据获取异常:子组件ngModel绑定后父组件数据为空
问题描述
我创建了NewInvoiceComponent与InvoiceItemListComponent两个组件,其中InvoiceItemListComponent用于处理发票项(包含count、unit、description、price字段)。已实现动态添加、删除输入字段的功能,相关按钮运行正常,但提交表单时invoiceItems数组内的项仍为null。我在InvoiceItemListComponent中使用了[(ngModel)],请问这些动态输入框能否使用ngModel?或是@Output存在问题?
代码实现
父组件(NewInvoiceComponent)
TypeScript代码
export class NewInvoiceComponent implements OnInit { public invoiceItems: InvoiceItem[] = []; constructor() { } ngOnInit(): void { } addInvoiceItem(): void { let next = 0; if (this.invoiceItems.length > 0) { next = this.invoiceItems.length; } this.invoiceItems.push({count: null, description: null, price: null, unit: null, id: next}); } deleteInvoiceItem(item: InvoiceItem): void { this.invoiceItems = this.invoiceItems.filter(element => element.id !== item.id); } onSubmit(): void { console.log(this.invoiceItems); } }
HTML模板
<app-invoice-item-list [invoiceItemList]="invoiceItems" (onDelete)="deleteInvoiceItem($event)"></app-invoice-item-list> <button class="btn btn-primary" type="button" (click)="addInvoiceItem()">New item</button> <!-- another inputs --> <div class="col-lg-12"> <button class="btn btn-primary" type="submit">Create invoice</button> </div>
子组件(InvoiceItemListComponent)
TypeScript代码
export class InvoiceItemListComponent implements OnInit { @Input() invoiceItemList = []; // tslint:disable-next-line:no-output-on-prefix @Output() onDelete = new EventEmitter<any>(); constructor() { console.log(this.invoiceItemList); } ngOnInit(): void { } onDeleteInvoiceItem(invoiceItem) { console.log(invoiceItem); this.onDelete.emit(invoiceItem); } }
HTML模板
<div class="row" *ngFor="let invoice of invoiceItemList"> <div class="col-md-2"> <div class="form-group"> <label class="form-control-label" for="input-count">Count</label> <input id="input-count" name="count" class="form-control form-control-alternative" [(ngModel)]="invoice.count" type="number"> </div> </div> <div class="col-md-2"> <div class="form-group"> <label class="form-control-label" for="input-type">Unit</label> <input id="input-type" name="type" class="form-control form-control-alternative" type="text" placeholder="ks, hod" [(ngModel)]="invoice.unit"> </div> </div> <div class="col-md-4"> <div class="form-group"> <label class="form-control-label" for="input-description">Description</label> <input id="input-description" name="description" class="form-control form-control-alternative" placeholder="Popis položky" type="text" [(ngModel)]="invoice.description"> </div> </div> <div class="col-md-2"> <div class="form-group"> <label class="form-control-label" for="input-item-price">Price</label> <input id="input-item-price" name="address" class="form-control form-control-alternative" placeholder="Cena" type="text" [(ngModel)]="invoice.price"> </div> </div> <div class="col-md-2"> <div class="form-group"> <button class="btn btn-danger" type="button" (click)="onDeleteInvoiceItem(invoice)">Delete</button> </div> </div> </div>
问题分析与解决方案
动态输入框完全可以使用
[(ngModel)],你的问题既不是ngModel的使用限制,也不是@Output的问题——删除功能正常说明@Output的实现是正确的。核心问题:
ngModel未正确绑定
当[(ngModel)]没有包裹在<form>标签内时,Angular默认会将其视为表单控件的一部分,此时必须添加[ngModelOptions]="{standalone: true}"来告诉Angular该输入框是独立的,否则双向绑定无法生效。修改方案
在子组件的所有[(ngModel)]绑定的输入框上添加[ngModelOptions]="{standalone: true}",示例如下:<input id="input-count" name="count" class="form-control form-control-alternative" [(ngModel)]="invoice.count" type="number" [ngModelOptions]="{standalone: true}">对所有四个输入框执行相同修改即可。
额外优化建议
- 给子组件的
@Input指定明确类型:@Input() invoiceItemList: InvoiceItem[] = [];,保持类型一致性,避免潜在错误。 - 父组件模板中的提交按钮建议包裹在
<form>标签内(并添加(ngSubmit)="onSubmit()"),这样更符合Angular表单的规范,也可以省去standalone配置:<form (ngSubmit)="onSubmit()"> <app-invoice-item-list [invoiceItemList]="invoiceItems" (onDelete)="deleteInvoiceItem($event)"></app-invoice-item-list> <button class="btn btn-primary" type="button" (click)="addInvoiceItem()">New item</button> <!-- another inputs --> <div class="col-lg-12"> <button class="btn btn-primary" type="submit">Create invoice</button> </div> </form>
- 给子组件的
内容的提问来源于stack exchange,提问作者dodo
相关产品推荐
相关产品推荐

