如何使组件sub
中声明的<mat-list-option>
"订阅"组件sub
外部的<mat-selection-list>
(例如组件app
)?
(不幸的是,我无法使Stackblitz与我公司的代理一起工作,所以我只放我的例子的相关部分)
示例1(工作,无组件sub
)
(应用程序组件.html)
<div>{{selections | json}}</div>
<mat-selection-list [(ngModel)]="selections">
<mat-list-option [value]="{x: 1}">x: 1</mat-list-option>
<mat-list-option [value]="{x: 2}">x: 2</mat-list-option>
<mat-list-option [value]="{y: 1}">y: 1</mat-list-option>
<mat-list-option [value]="{y: 2}">y: 2</mat-list-option>
</mat-selection-list>
(app.component.ts)
@Component({
templateUrl: './app.component.html',
})
export class AppComponent {
selections = [];
}
此示例按预期工作。所有 4 个选项都被渲染,它们的选择反映回selections
属性中(所有选项的值都是 javascript 对象,并且它们被正确插入/省略selections
数组)。
示例 2(不起作用,组件sub
<mat-selection-list>
和<mat-list-option>
之间添加)
(应用程序组件.html)
<div>{{selections | json}}</div>
<mat-selection-list [(ngModel)]="selections">
<sub></sub>
</mat-selection-list>
(子组件.html)
<mat-list-option [value]="{x: 1}">x: 1</mat-list-option>
<mat-list-option [value]="{x: 2}">x: 2</mat-list-option>
<mat-list-option [value]="{y: 1}">y: 1</mat-list-option>
<mat-list-option [value]="{y: 2}">y: 2</mat-list-option>
(app.component.ts unchanged;sub.component.ts trivial)
此示例按预期呈现所有选项。他们的选择不会反映回selections
属性(正如预期的那样,因为在实例化每个<mat-list-option>
时,没有可见的<mat-selection-list>
供他们订阅)。
示例 3(尝试转发<mat-selection-list>
,但无济于事)
(app.component.ts)
@Component({
...
viewProviders: [{ provide: MatSelectionList, useExisting: MatSelectionList }]
})
export class AppComponent {
selections = [];
}
我预计这个会起作用。但我只能得到一个错误:
Cannot instantiate cyclic dependency! MatSelectionList (...)
如何做到这一点?
注意
我想观察一下,ngModel
指令(与ngForm
和/或ngModelGroup
协同工作)只需向一个实例化ngForm
或ngModelGroup
(包括)和一个实例化ngModel
(独占)之间的所有干预组件添加适当的viewProviders
即可跨模板边界完美运行。
不过,它们的注射途径并不相同:ngModel
通过[来源]获得其父ControlContainer
(包含ngForm
和ngModelGroup
):
constructor(@Optional() @Host() parent: ControlContainer, ...) {...}
虽然<mat-list-option>
通过[来源]这样做:
constructor(..., @Inject(forwardRef(() => MatSelectionList)) public selectionList: MatSelectionList) {...}
我不精通角度来了解差异及其含义。
MatSelectList 的内置 SelectionModel 与示例 2 方法配合使用。问题是NgModel(这可能是错误或固有限制)。您可以通过侦听列表的选择更改并直接管理模型来解决此问题。例如:
.HTML
<mat-selection-list [ngModel]="selections" (selectionChange)="handleSelectionChange($event.option)">
<sub></sub>
</mat-selection-list>
TS
selections = [];
handleSelectionChange(option: MatSelectionListChange) {
if (option.selected) {
this.selections.push(option.value);
}
else {
const index = this.selections.indexOf(option.value);
this.selections.splice(index, 1);
}
}