Angular CDK: Как установить Входы в ComponentPortal
Я хотел бы использовать новый портал из материала CDK для добавления динамического содержимого в несколько частей формы.
У меня сложная структура формы, и цель состоит в том, чтобы иметь форму, указывающую несколько мест, где подкомпоненты могут (или нет) внедрять шаблоны.
Может быть, CDK Portal - не лучшее решение для этого?
Я пытался что-то, но я уверен, что это не так: https://stackblitz.com/edit/angular-yuz1kg
Я пробовал также с new ComponentPortal(MyPortalComponent)
но как мы можем установить входы на него? Обычно это что-то вроде componentRef.component.instance.myInput
Ответы
Ответ 1
Вы можете создать собственный инжектор и внедрить его в созданный вами портал компонентов. -
createInjector(dataToPass): PortalInjector {
const injectorTokens = new WeakMap();
injectorTokens.set(CONTAINER_DATA, dataToPass);
return new PortalInjector(this._injector, injectorTokens);
}
CONTAINER_DATA - это пользовательский инжектор (InjectorToken), созданный -
export const CONTAINER_DATA = new InjectionToken<{}>('CONTAINER_DATA');
Чтобы потреблять созданный инжектор, используйте -
let containerPortal = new ComponentPortal(ComponentToPort, null, this.createInjector({
data1,
data2
}));
overlay.attach(containerPortal);
оверлей является экземпляром OverlayRef (который является порталом выхода)
Внутри "ComponentToPort" вам нужно будет ввести созданный инжектор -
@Inject(CONTAINER_DATA) public componentData: any
Подробнее об этом здесь -
-
https://github.com/angular/material2/issues/8322
-
https://github.com/angular/material2/issues/8322
Ответ 2
Вы можете ввести данные в ComponentPortal с помощью специального инжектора, переданного в 3-м параметре ComponentPortal (исправить проблему синтаксиса: невозможно разрешить все параметры для компонента: ([объект объекта], [объект объекта],?).
export const PORTAL_DATA = new InjectionToken<{}>('PortalData');
class ContainerComponent {
constructor(private injector: Injector, private overlay: Overlay) {}
attachPortal() {
const componentPortal = new ComponentPortal(
ComponentToPort,
null,
this.createInjector({id: 'first-data'})
);
this.overlay.create().attach(componentPortal);
}
private createInjector(data): PortalInjector {
const injectorTokens = new WeakMap<any, any>([
[PORTAL_DATA, data],
]);
return new PortalInjector(this.injector, injectorTokens);
}
}
class ComponentToPort {
constructor(@Inject(PORTAL_DATA) public data ) {
console.log(data);
}
}
Ответ 3
Можно установить компонентные входы (или привязать к выходам как наблюдаемые) следующим образом:
portal = new ComponentPortal(MyComponent);
this.portalHost = new DomPortalHost(
this.elementRef.nativeElement,
this.componentFactoryResolver,
this.appRef,
this.injector
);
const componentRef = this.portalHost.attach(this.portal);
componentRef.instance.myInput = data;
componentRef.instance.myOutput.subscribe(...);
componentRef.changeDetectorRef.detectChanges();