角度材质<mat-selection-list>和<mat-list-option>跨模板边界



如何使组件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协同工作)只需向一个实例化ngFormngModelGroup(包括)和一个实例化ngModel(独占)之间的所有干预组件添加适当的viewProviders即可跨模板边界完美运行。

不过,它们的注射途径并不相同:ngModel通过[来源]获得其父ControlContainer(包含ngFormngModelGroup):

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);
}
}

最新更新