我遇到了一个问题,即没有md
前缀的HTML元素(例如<input mdInput>
)与其基础模型保持同步,但那些是<md-select>
和{{}} {1}} 未更新,因此与基础模型不同步。
注意 - 我无法在此this Plunker中重新创建问题 - 但是,我的代码非常类似于我在本地运行的代码。我不知道如何进一步调查,所以我在这里尝试任何想法。
TL,DR - 我了解组件视图可能与其基础模型不同步,但会导致某些 UI元素(<md-checkbox>
)保持同步而其他人不同步(<input>
和<md-checkbox>
)?
只有在事件(<md-select>
,mouseover
,hover
等)触发变更检测时才会同步后者?
详细信息 - 一个线索可能是在md-checkbox上使用click
导致复选框变得不同步:
[(ngModel)]
但是,更改此项以绑定到该值,确保复选框保持同步(请参阅以下内容中添加<!-- Checkbox wasn't updated in UI until change detection triggered. -->
<md-checkbox [(ngModel)]="node.checked" name="checked"></md-checkbox>
:
checked="{{node.checked}}"
所以我假设类似的问题正在影响<!-- This always remains in-sync. -->
<md-checkbox [(ngModel)]="node.checked" name="checked" checked="{{node.checked}}">
,只是我无法直接绑定到该值,因此它仍然不同步。
有关显示JSON“树”的递归呈现组件的示例,请参阅this Plunker。每个JSON对象(即节点)由四个字段组成:
<md-select>
title:string
checked:boolean
types:[]
children:[]
,title
和checked
字段只是虚拟值,但故意选择代表不同的材料设计表单字段:
types
- 简单。<input mdInput>
- 复杂。<md-checkbox>
- 复杂。 <md-select>
字段是“树”的形成方式。叶节点不会有children
,但父节点将
Leaf节点:children
非叶节点:
{'title': 'L1-A', 'checked': false, 'types': ['NUMBER']}
我已经硬编码了两个代表起始状态和更新状态的JSON对象:
{
'title': 'L1-A',
'checked': false,
'types': ['NUMBER'],
'children': [
'title': 'L2-A',
'checked': false,
'types': ['NUMBER'],
]
}
您可能会看到JSON树结构相同但标题不同。 export class Tree {
treeStart:any = {
'title' : 'L0',
'checked': false,
'types': ['NUMBER']
'children' : [
{'title': 'L1-A',
'checked': false,
'types': ['STRING']
'children' : [
{'title': 'L2-A','checked': false,'types': ['INTEGER']}
]
}
]
};
treeUpdated:any = {
'title' : 'L0-UPDATED',
'checked': true,
'types': ['NUMBER']
'children' : [
{'title': 'L1-A-UPDATED',
'checked': true,
'types': ['NUMBER']
'children' : [
{'title': 'L2-A-UPDATED','checked': true,'types': ['NUMBER']}
]
}
]
};
tree:any;
constructor(private cdRef: ChangeDetectorRef) {
this.tree = this.treeStart;
}
}
开始checked:false
进行更新。 checked:true
是根节点。
两个Angular 2组件呈现JSON:
L0
tree-component.ts / tree-component.html
node-component.ts / node-component.html
通过渲染单个tree
来解决问题。 node
然后以递归方式为任何node
呈现自己。
使用children
呈现的根节点(树):
tree-component.html
<md-card>
<app-node [node]="tree"></app-node>
</md-card>
递归渲染:
node-component.html
更新和重置按钮被添加到tree-component.html,因为更新和重置适用于树级别。
<!-- Checked -->
<md-checkbox [(ngModel)]="node.checked" name="checked"></md-checkbox>
<!-- Title -->
<md-input-container>
<input mdInput placeholder="Title"
#name="ngModel" [(ngModel)]="node.title"
name="title" value="{{node?.title}}">
</md-input-container>
<!-- Types -->
<md-select placeholder="Type" multiple="true" color="accent [(ngModel)]="node.types">
<md-option *ngFor="let type of allTypes" [value]="type.value {{type.display}}</md-option>
</md-select>
<!-- Recursive rendering -->
<md-card *ngFor="let child of node?.children">
<app-node *ngIf="child" [node]="child"></app-node>
</md-card>
单击Plunker example中的<button md-raised-button (click)="update()">Update</button>
<button md-raised-button (click)="reset()">Reset</button>
按钮,在任意超时(模拟API调用)后加载更新的树:
update
呈现的JSON数量可能会非常大,后续树可能会非常深和/或很宽。因此,节点组件使用change push detection strategy:
update(): void {
setTimeout(() => {
this.apiCallback();
}, 2000);
}
apiCallback(): void {
this.tree = this.treeUpdated;
this.cdRef.detectChanges();
}
树组件使用默认更改检测。
我遇到的问题是@Component({
selector: 'app-node',
templateUrl: './src/node.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class Node implements OnInit {
/* Node implementation goes here. */
}
这样的'简单'材料设计表单字段始终与模型保持同步,但mdInput
等“复杂”表单字段在更新之前不会更新事件发生。