【问题标题】:Get Parent ViewContainerRef from inside projected child component Angular 5从投影的子组件Angular 5内部获取父ViewContainerRef
【发布时间】:2023-03-09 06:44:01
【问题描述】:

我有一个带有动态创建组件的 App 组件。 父组件有一个<ng-content> 元素,这样我们就可以在父组件中投影我们的子组件。

应用组件:

@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>
                `
})

我的问题是,有什么方法可以访问子组件内的 App 组件的 ViewContainerRef (#parentcontainer) 吗?目标是稍后在#parentcontainer 中动态插入其他组件,例如在子组件中单击某些按钮。

这是StackBlitz 上的工作示例

【问题讨论】:

  • 不确定您的任务是什么。如果要传递容器,只需使用数据绑定。但是,如果您想使用容器通过子组件的操作将动态组件插入到父组件中,我不确定这是正确的方法。我只是向上发送一个带有相关数据的事件,然后让父组件添加该组件。

标签: angular angular5


【解决方案1】:

您可以从子组件中创建一个新组件,并将其 HTML 元素附加到 DOM 中您喜欢的任何位置

// 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)

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

或者,为了让组件在应用期间保持活动状态,创建一个服务并在 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

最佳解决方案可能是为 Portal 和 PortalHost 使用 Angular Material CDK 功能。它很新,但它的目的是在 Angular 应用程序中创建在实际 my-app 元素之外运行的组件 - 这可能是一个更好的长期解决方案 - 它用于在他们的示例中制作模态等

【讨论】:

  • 事后看来(即使我的回答被接受了),我认为子组件确实应该调度事件,通知父/其他组件要创建新组件。由于您正在使用 并将子项投影到其中,因此您可以在模板中同时包含父项和子项的组件中完成此操作。我的回答适用于与应用程序流程的其余部分没有特别关联的非常动态的内容,但这不是标准做法
猜你喜欢
  • 2020-12-08
  • 1970-01-01
  • 1970-01-01
  • 2021-03-14
  • 2017-10-27
  • 2020-03-21
  • 2018-12-01
  • 2018-07-15
  • 2018-09-15
相关资源
最近更新 更多