首页 文章

从投影子组件Angular 5中获取父ViewContainerRef

提问于
浏览
1

我有一个包含动态创建组件的App组件 . 父组件具有 <ng-content> 元素,以便我们可以在Parent组件中投影子组件 .

应用组件:

@Component({
  selector: 'my-app',
  template:`<ng-container #parentcontainer></ng-container>`,
})

父组件:

@Component({
  selector: 'parent',
  template: `
  <ng-container #container></ng-container>
  <ng-content></ng-content>

                `
})

子组件:

@Component({
  selector: 'child',
  template: `<label>
                <input type="radio">
              </label>
                `
})

我的问题是,有没有办法在Child组件中访问App组件的ViewContainerRef(#parentcontainer)?目标是在稍后阶段动态插入#parentcontainer中的其他组件,就像从子组件点击一些按钮一样 .

这是StackBlitz上的工作样本

1 回答

  • 3

    你可以 create a new component from within the child component ,并在DOM中的任何地方附加它的HTML元素

    // remember to add YourComponent to entryComponents: [] of the module
    let componentFactory = this.componentFactoryResolver.resolveComponentFactory(YourComponent);
    let componentRef = viewContainerRef.createComponent(componentFactory, index);
    
    componentRef.instance.model = model; // where model is an input
    componentRef.changeDetectorRef.detectChanges(); // update it's view
    let htmlElement = (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
    
    // Now do what you want with the htmlElement e.g. document.querySelector('body').appendChild(htmlElement)
    

    这对你有用吗?请注意,只要子组件处于活动状态,该组件将仅保持活动状态

    或者, to keep the components alive for the app duration ,创建服务并在AppComponent级别提供一次 . 请注意,这使用 ApplicationRef ,它允许您调用attachView() - 这可能是一个解决方案

    constructor(
          private componentFactoryResolver: ComponentFactoryResolver,
          private appRef: ApplicationRef,
          private injector: Injector
      ) { }
    
      appendComponentToBody(component: any) {
        const componentRef = this.componentFactoryResolver
          .resolveComponentFactory(component)
          .create(this.injector);    
        this.appRef.attachView(componentRef.hostView);
        const domElem = (componentRef.hostView as EmbeddedViewRef<any>)
          .rootNodes[0] as HTMLElement;    
        // Append to body or wherever you want
        document.body.appendChild(domElem);
      }
    

    有关服务的详细信息example here

    best solution 可能使用 Angular Material CDK 功能 Portal and PortalHost . 它's pretty new, but it'的目的是从一个在实际的my-app元素之外运行的Angular应用程序中创建组件 - 这可能是一个更好的长期解决方案 - 它用于在他们的示例中制作模态等

相关问题