Angular4 - 3级自定义组件,孙子(ngModelChange)总是看到同一个祖父母
Angular4 - 3 level custom components, grandchild (ngModelChange) always sees same grandparent
我有一个 top-level 组件,在模板中有这个:
<cw-card-list [cards]="cards">
</cw-card-list>
当组件加载时,卡片从 API 填充:
private getCards(): void{
this._cardService.getCards().subscribe(
result => {
this.cards = result;
}
);
}
card-list 组件非常基础:
<div *ngFor="let card of cards; let i = index">
<cw-card-list-item
[card]="card" [index]="i">
</cw-card-list-item>
</div>
您可以看到列表中的每张卡片都是 card-list-item child:
中的一个 Input
export class CardListItemComponent implements OnInit, AfterViewInit {
@Input() card: Card;
@Input() index: number;
...
最后,每个 list-item 组件也有一个 child:
<cw-checklist-show [template]="card.template"
</cw-checklist-show>
export class ChecklistShowComponent implements OnInit {
@Input() template: Template
...
一切正常,显示所有数据。
但是,在这个最终组件中有一个复选框,它绑定到每个 child(一个 TemplateItem)的 属性 'is_completed':
<div *ngFor="let child of template.template_items; let i=index">
<input id="checkbox-{{i}}" type="checkbox"
[ngModel]="child.is_completed"
(ngModelChange)="onItemIsCompletedChange(i)">
</div>
每次 (ngModelChange) 事件触发时,它总是修改列表中 第一张卡片 的模板的 'is_completed' 属性,而不是一个点击。
为什么会这样?我什至尝试将输出事件连接到 parent 并且控制台记录了模板 - 它总是列出相同的模板,卡片列表数组中的项目 [0]!
但是如果我console.logthis.cards
在grandparent,它显示正确的模板附加到每张卡!
数据结构
每张卡片都有一个模板,像这样:
import { Template } from './template';
export class Card {
constructor() {
}
public id: string
public customer_id: string
public template: Template
public follow_up: Date
public is_new: boolean = true
}
每个模板都有一个 TemplateItem 数组:
import { TemplateItem } from './template-item';
export class Template {
constructor(
) {}
public id: string
public account_id: string
public name: string
public template_items: Array<TemplateItem>
public template_type: string
public status: string
}
每个TemplateItem是这样的:
export class TemplateItem {
constructor(
) {}
public id: string
public template_id: string
public sort: number
public content: string
public item_type: string
public is_completed: boolean = false
}
如果您像我一样习惯于构建模型驱动的表单,这可能不会立即显而易见,但输入的 ID 至关重要。
由于我的输入使用的是 INDEX,这意味着我页面上的复选框没有不同的 ID:
checkbox-{{i}}
这意味着点击它总是会在第一张卡片的复选框(例如 checkbox-0、checkbox-1)上触发事件,因为显然每个孙子 (TemplateItem) 都是一个从 0...n 开始的数组。
所以解决方案是:
<input id="checkbox-{{child.id}}-{{i}}" type="checkbox"
[ngModel]="child.is_completed"
(ngModelChange)="onItemIsCompletedChange(i)">
现在每个复选框都有一个唯一的 ID,特定于孙子 TemplateItem 的 ID。
我有一个 top-level 组件,在模板中有这个:
<cw-card-list [cards]="cards">
</cw-card-list>
当组件加载时,卡片从 API 填充:
private getCards(): void{
this._cardService.getCards().subscribe(
result => {
this.cards = result;
}
);
}
card-list 组件非常基础:
<div *ngFor="let card of cards; let i = index">
<cw-card-list-item
[card]="card" [index]="i">
</cw-card-list-item>
</div>
您可以看到列表中的每张卡片都是 card-list-item child:
中的一个 Inputexport class CardListItemComponent implements OnInit, AfterViewInit {
@Input() card: Card;
@Input() index: number;
...
最后,每个 list-item 组件也有一个 child:
<cw-checklist-show [template]="card.template"
</cw-checklist-show>
export class ChecklistShowComponent implements OnInit {
@Input() template: Template
...
一切正常,显示所有数据。
但是,在这个最终组件中有一个复选框,它绑定到每个 child(一个 TemplateItem)的 属性 'is_completed':
<div *ngFor="let child of template.template_items; let i=index">
<input id="checkbox-{{i}}" type="checkbox"
[ngModel]="child.is_completed"
(ngModelChange)="onItemIsCompletedChange(i)">
</div>
每次 (ngModelChange) 事件触发时,它总是修改列表中 第一张卡片 的模板的 'is_completed' 属性,而不是一个点击。
为什么会这样?我什至尝试将输出事件连接到 parent 并且控制台记录了模板 - 它总是列出相同的模板,卡片列表数组中的项目 [0]!
但是如果我console.logthis.cards
在grandparent,它显示正确的模板附加到每张卡!
数据结构
每张卡片都有一个模板,像这样:
import { Template } from './template';
export class Card {
constructor() {
}
public id: string
public customer_id: string
public template: Template
public follow_up: Date
public is_new: boolean = true
}
每个模板都有一个 TemplateItem 数组:
import { TemplateItem } from './template-item';
export class Template {
constructor(
) {}
public id: string
public account_id: string
public name: string
public template_items: Array<TemplateItem>
public template_type: string
public status: string
}
每个TemplateItem是这样的:
export class TemplateItem {
constructor(
) {}
public id: string
public template_id: string
public sort: number
public content: string
public item_type: string
public is_completed: boolean = false
}
如果您像我一样习惯于构建模型驱动的表单,这可能不会立即显而易见,但输入的 ID 至关重要。
由于我的输入使用的是 INDEX,这意味着我页面上的复选框没有不同的 ID:
checkbox-{{i}}
这意味着点击它总是会在第一张卡片的复选框(例如 checkbox-0、checkbox-1)上触发事件,因为显然每个孙子 (TemplateItem) 都是一个从 0...n 开始的数组。
所以解决方案是:
<input id="checkbox-{{child.id}}-{{i}}" type="checkbox"
[ngModel]="child.is_completed"
(ngModelChange)="onItemIsCompletedChange(i)">
现在每个复选框都有一个唯一的 ID,特定于孙子 TemplateItem 的 ID。