Angular中ng-content渲染mat-list-option报错:无SelectionList注入提供者
问题原因与解决方案
报错根源
当你在LicenseSelectModalComponent中直接通过ng-content传入mat-list-option时,这些列表项是在父组件的注入上下文中创建的,但mat-list-option依赖SelectionList(Angular Material为mat-selection-list提供的注入令牌),而这个令牌仅在BaseSelectModalComponent内部的mat-selection-list所在的上下文里才会被提供,父组件中没有对应的提供者,因此触发NullInjectorError。
解决方法:改用模板传递自定义内容
放弃ng-content的方式,通过ng-template将自定义列表项模板传递给基础组件,让模板在子组件的上下文里渲染,这样mat-list-option就能获取到SelectionList的提供者。
步骤1:修改BaseSelectModalComponent
- 添加输入属性接收自定义模板:
import { Input, TemplateRef } from '@angular/core'; export class BaseSelectModalComponent { @Input() customItemTemplate?: TemplateRef<any>; // 保留原有其他属性与逻辑 }
- 更新模板,根据是否传入自定义模板来渲染内容:
<mat-selection-list class="pt-0" [multiple]="false" #list> <!-- 渲染自定义模板 --> @if (customItemTemplate) { @for (item of items(); track $index) { <ng-container [ngTemplateOutlet]="customItemTemplate" [ngTemplateOutletContext]="{ $implicit: item }" ></ng-container> } } @else { <!-- 默认列表项 --> @for (item of items(); track $index) { <mat-list-option [value]="{ id: item.id, name: item.name }">{{ item.name }}</mat-list-option> } } </mat-selection-list>
步骤2:修改LicenseSelectModalComponent
将原来的自定义列表项放到ng-template中,并传递给基础组件:
@Component({ selector: 'app-product-select-modal', standalone: true, imports: [BaseSelectModalComponent, MatListOption], template: ` <app-base-select-modal title="Seleziona la licenza" [items]="items()" [itemsCount]="count()" [isLoading]="isLoading()" (onClose)="close()" (onConfirm)="confirm($event)" [customItemTemplate]="customItemTpl" > </app-base-select-modal> <!-- 自定义列表项模板 --> <ng-template #customItemTpl let-item> <mat-list-option [value]="item"> <div>{{ item.product.name }}</div> <span>{{ item.key }}</span> </mat-list-option> </ng-template> `, }) export class LicenseSelectModalComponent { // 保留原有其他属性与逻辑 }
为什么这个方法有效?
ng-template本身不会渲染任何内容,只有当通过ngTemplateOutlet在子组件内部渲染时,模板里的mat-list-option才会在子组件的注入上下文里被创建,此时就能找到mat-selection-list提供的SelectionList令牌,解决依赖注入的问题。
内容的提问来源于stack exchange,提问作者NiceToMytyuk
相关产品推荐
相关产品推荐

