这是答案
这是 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()方法是从外部组件调用的方法。createInjector()是创建Injector的方法,它帮助我们将数据传递给组件( PComponent )。所以是时候在另一个组件中使用我们的服务了。
例子.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:表达式在检查后已更改。以前的值:'null:未定义'。当前值:'null:测试文本'。似乎视图是在对其父级及其子级进行脏检查之后创建的。它是在变更检测挂钩中创建的吗?
页面刷新后,您将看到自动生成并发布在 bpage 标记中的 PComponent 的内容
希望对你有帮助