我有以下服务
@Injectable()
export class PService {
private loadPComponent: ComponentPortal<PComponent>;
private bodyPortalHost: DomPortalHost;
constructor(private appRef: ApplicationRef,
private componentFactoryResolver:
ComponentFactoryResolver,
private injector: Injector) {
this.loadPComponent = new ComponentPortal(PComponent);
}
instance(elementRef: Element) {
this.bodyPortalHost = new DomPortalHost(elementRef,
this.componentFactoryResolver, this.appRef, this.injector);
}
show() {
const componentRef: ComponentRef<PComponent> =
this.bodyPortalHost.attach(this.loadPComponent);
}
hide() {
this.bodyPortalHost.detach();
}
}
所以,我有一个组件calle“PComponent”,并从该服务我创建dinamically组件 这个班有两种方法 instance - 传递调用服务的组件的Element show - 附加已经“创建”的PComponent
一切正常,Portal是一个很棒的解决方案! 但我的PComponent有一个带有一些变量的HTML模板,例如
{{imageURL}}
应该是图片网址,并将该图片显示为PComponent中的div内容。 问题 我如何将imageURL字符串传递给服务或组件?
提前致谢
答案 0 :(得分:2)
这是答案
这是Pcomponent代码,该组件应该从另一个组件创建。 的 p.component.ts 强>
@Component({
selector: 'app-p',
templateUrl: './p.component.html',
styleUrls: ['./p.component.css']
})
export class PComponent implements OnInit {
name: string = '';
constructor(@Inject(CONTAINER_DATA) public componentData: any) { }
ngOnInit() {
console.log(this.componentData.data.test);
}
}
所以我们必须注入CONTAINER_DATA InjectionToken,从该变量可以获取从其他组件传递的数据。 CONTAINER_DATA变量在服务文件中创建。 的 p.service.ts 强>
import {ApplicationRef, ComponentFactoryResolver, ComponentRef, Injectable, InjectionToken, Injector} from '@angular/core';
import {CONTAINER_DATA, PComponent} from './p.component';
import {
ComponentPortal,
DomPortalHost, PortalInjector
} from '@angular/cdk/portal';
export const CONTAINER_DATA = new InjectionToken<{}>('CONTAINER_DATA');
@Injectable()
export class PService {
private loadPComponent: ComponentPortal<PComponent>;
private bodyPortalHost: DomPortalHost;
constructor(private appRef: ApplicationRef,
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector) { }
instance(elementRef: Element, data) {
this.loadPComponent = new ComponentPortal(PComponent, null,
this.createInjector({data}));
this.bodyPortalHost = new DomPortalHost(elementRef,
this.componentFactoryResolver, this.appRef, this.injector);
}
show() {
const componentRef: ComponentRef<PComponent> =
this.bodyPortalHost.attach(this.loadPComponent);
}
createInjector(dataToPass): PortalInjector {
const injectorTokens = new WeakMap();
injectorTokens.set(CONTAINER_DATA, dataToPass);
return new PortalInjector(this.injector, injectorTokens);
}
hide() {
this.bodyPortalHost.detach();
}
}
因此,在服务中我们使用@ angular / cdk / portal来获取PComponent实例。 instance()和 show()方法是从外部Component调用的方法。 createInjector()是创建 Injector 的方法,它帮助我们将数据传递给组件(PComponent)。 所以现在是时候在另一个组件中使用我们的服务了。 的 example.component.ts 强>
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit {
@ViewChild('bpage', {read: ElementRef}) tref: ElementRef;
constructor(private route: ActivatedRoute, private pService:
PService, private contentService: ContentService) { }
ngOnInit() {
Promise.resolve().then(() => {
this.pService.instance(this.tref.nativeElement, {'test':
'prueba'});
}
}
该组件在html模板中有一个类似的标记:
<div #bpage></div>
在此标记中应收取来自PComponent并从PService注入的内容。 在OnInit方法中,我们必须将服务调用封装到Promise中,这样可以避免以下错误:
ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后发生了变化。上一个值:&#39; null:undefined&#39;。当前值:&#39; null:测试文字&#39;。看起来这个视图是在其父级及其子级被脏检查后创建的。它是否已在变更检测钩子中创建?
页面刷新后,您将看到自动生成并在bpage标签中发布的PComponent的内容
希望对你有所帮助