【发布时间】:2023-04-01 21:28:01
【问题描述】:
我在创建自定义 cdkOverlay 弹出框组件时出现问题。它通过单击过滤器图标在表格中打开。表很少有这样的图标。 这就是我的 Popover 组件服务的外观。它作为普通的角度材质对话框打开。
@Injectable()
export class PopoverService {
constructor(
private overlay: Overlay,
private injector: Injector
) { }
open<T = unknown, R = unknown>(component: ComponentType<T>, elementRef: ElementRef, config: PopoverConfig = {}): PopoverRef<R> {
const popoverConfig: PopoverConfig = { ...DEFAULT_CONFIG, ...config };
const overlayRef: OverlayRef = this.overlay.create(this.getOverlayConfig(elementRef, popoverConfig));
const popoverRef: PopoverRef<R> = new PopoverRef<R>(overlayRef);
const popupPortal: ComponentPortal<T> =
new ComponentPortal<T>(component, null, this.createInjector(this.injector, popoverRef, config.data));
overlayRef.attach(popupPortal);
overlayRef.backdropClick().subscribe(_ => popoverRef.close());
return popoverRef;
}
private createInjector(injector: Injector, popoverRef: PopoverRef, data: unknown): Injector {
return Injector.create({
providers: [
{ provide: PopoverRef, useValue: popoverRef },
{ provide: POPOVER_DATA, useValue: data }
],
parent: injector
});
}
private getOverlayConfig(elementRef: ElementRef, config: PopoverConfig): OverlayConfig {
return new OverlayConfig({
...config,
positionStrategy: this.getOverlayPositions(elementRef),
scrollStrategy: this.overlay.scrollStrategies.reposition()
});
}
private getOverlayPositions(elementRef: ElementRef): PositionStrategy {
return this.overlay.position()
.flexibleConnectedTo(elementRef)
.withPositions(this.getPositions())
.withFlexibleDimensions(false)
.withPush(false);
}
private getPositions(): ConnectedPosition[] {
return [
{
originX : 'center',
originY : 'bottom',
overlayX: 'start',
overlayY: 'top',
},
{
originX : 'center',
originY : 'top',
overlayX: 'start',
overlayY: 'bottom',
},
{
originX : 'center',
originY : 'bottom',
overlayX: 'end',
overlayY: 'top',
},
{
originX : 'center',
originY : 'top',
overlayX: 'end',
overlayY: 'bottom',
},
];
}
}
我还创建了 PopoverRef 类,其中包括对覆盖的引用。
export class PopoverRef<T = unknown>{
afterClosed$ = new Subject<OverlayCloseEvent<T>>();
constructor(private overlayRef: OverlayRef) {
overlayRef.backdropClick().subscribe(() => this.overlayClose('backdropClick', null));
}
close(data?: T): void {
this.overlayClose('close', data);
}
private overlayClose(type: 'backdropClick' | 'close', data: T) {
this.overlayRef.dispose();
this.afterClosed$.next({
type,
data
});
this.afterClosed$.complete();
}
}
弹出框内的组件通过this.popoverRef.close(profile) 向父级传递数据
我希望在父组件中我可以做这样的事情并接收数据this.popoverRef.afterClosed$.subscribe((res) => this.someEmitter.emit(res))
但结果我在控制台中看到错误
错误 NullInjectorError: R3InjectorError(TableModule)[PopoverRef -> PopoverRef -> PopoverRef -> PopoverRef -> PopoverRef -> PopoverRef]:
NullInjectorError:没有 PopoverRef 的提供者!
但如果 afterClosed$ 在 popover 组件中订阅,一切正常
更新 父组件
@ViewChild(CdkOverlayOrigin) cdkOverlayOrigin: CdkOverlayOrigin;
@Input() filterType: TableFilterType;
@Input() filterData: TableStaticData[];
constructor(
private popoverRef: PopoverRef
) {}
onOpenPopover(event: Event): void {
event.stopPropagation();
this.popoverStore.dispatch(new fromPopoverStore.OpenFilterPopover({
filterType: this.filterType,
elRef: this.cdkOverlayOrigin.elementRef,
filterItemData: this.filterItemData
}));
this.popoverRef.afterClosed$.subsribe();
}
【问题讨论】:
-
好吧,您尝试在某处注入 PopoverRef,但它不包含在此代码中,因此我们无法为您提供帮助。
-
父组件打开popover,子组件通过父组件中的
this.popoverRef.close(someData)传递数据我尝试this.popoverRef.afterClosed$.subscribe()父组件在构造函数中注入PopoverRef,这个父组件有错误 -
是否愿意贴出父组件的代码(进入实际问题)?
-
你的父级不能在构造函数中注入 PopoverRef。
-
添加了父组件。无论如何,它没有给我答案,为什么我不能将它注入父级,即使它不是可注入的(以 OverlayRef 类为例),对于角度注入类也是正常的,以及将数据传递给父组件的解决方案是什么
标签: angular angular-material angular-cdk