Angular - 使用自定义指令加载多个组件返回未定义

Posted

技术标签:

【中文标题】Angular - 使用自定义指令加载多个组件返回未定义【英文标题】:Angular - Using custom directive to load several components is returning undefined 【发布时间】:2021-09-03 03:32:20 【问题描述】:

我正在开发一个应用程序,目前,我有一个动态网格生成器,它可以划分屏幕空间以动态适应多个组件。因此,它的组件必须在 Angular 渲染页面后渲染组件。为了实现这一点,我遵循了角度动态组件加载器指南 (https://angular.io/guide/dynamic-component-loader)。

所以我现在确实拥有必须渲染其他组件的组件,我有我的自定义指令来渲染组件。

指令

@Directive(
    selector: '[componentLoader]'
)
export class ComponentLoaderDirective 
    constructor ( 
        public ViewContainerRef: ViewContainerRef 
    ) 

现在的组件(网格组件) grid.component.ts

// ... Stuff above
export class GridComponent implements OnInit 

  @Input() public items: gridItem[] = [];
  @ViewChild(ComponentLoaderDirective) componentLoader: ComponentLoaderDirective | undefined;


  constructor(
    private sanitizer: DomSanitizer,
    private componentFactoryResolver: ComponentFactoryResolver 
  ) 

  ngOnInit(): void  this.processRow(this.items) 

  processRow( row: gridItem[] )  
    // Some grid related stuff ... 
    for ( let item of row )  
      // Stuff performed over every item in each grid row
      
      this.renderComponentIfNeeded(item)
    
  

  renderComponentIfNeeded( item: gridItem ):void 
    if ( item.components ) 
      let componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
      let viewContainerRef = this.componentLoader.ViewContainerRef;
      viewContainerRef.clear();
      let componentRef = viewContainerRef.createComponent<any>(componentFactory);
      componentRef.instance.data = item;

      console.log('Directive ', this.componentLoader, 'ComponentRef: ', componentRef);
    
  

以及组件的html

<!-- Dynamic grid generation using ng-template and ng-content. This is generated several times using the *ngFor, for every item in the items array we will have a componentLoader -->

<ng-template componentLoader>
</ng-template>

这些文件中有更多内容,但为简单起见,我只发布此内容,如果您需要更多代码,请告诉我。

好的,所以我的问题是当我访问this.contentLoader 时返回的值是未定义的,所以this.componentLoader.viewContainerRef 会导致错误,因为componentLoader 是未定义的。

我尝试将 exportAs 属性添加到指令的装饰器中,但它给出的错误完全相同。

我也尝试在模块声明中添加指令但没有成功,并将 &lt;ng-template componentLoader&gt; 更改为 &lt;ng-template #loader=componentLoader&gt; 导致不同的错误(没有指令有 'componentLoader' exportAs 或类似的东西)

PS:在 ´´´this.componentFacotryResolver.resolveComponentFactory(component)``` 中,我成功地拥有了已分配给网格的每个组件。

我希望您不要解决我的问题,而是为我指明正确的方向并帮助我了解我做错了什么以提高自己。

任何帮助将不胜感激:)

【问题讨论】:

【参考方案1】:

我已经设法以一种非常简单的方式解决了这个问题。

我试图在网格组件中做太多事情,所以我删除了与组件加载器相关的代码,并将其移动到一个名为 ComponentLoaderComponent 的组件中。

在组件内部,我以与在网格组件中相同的方式设置了所有逻辑。所以现在我有一个像这样的新 ts 文件:

import  Component, ComponentFactoryResolver, Input, OnInit, ViewChild  from '@angular/core';
import  ComponentLoaderDirective   from 'src/app/shared/directives/componentLoader.directive';

@Component(
  selector: 'component-loader',
  templateUrl: './component-loader.component.html',
  styleUrls: ['./component-loader.component.css']
)
export class ComponentLoaderComponent implements OnInit 

  @Input() public component: any;
  @ViewChild(ComponentLoaderDirective,  static: true ) componentLoader!: ComponentLoaderDirective;

  constructor(
    private componentFactoryResolver: ComponentFactoryResolver
  )  

  ngOnInit(): void 
    this.loadComponent();
  

  loadComponent():void 
    if (this.component) 
      let componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.component);
      let viewContainerRef = this.componentLoader.viewContainerRef;
      viewContainerRef.clear();
      let componentRef  = viewContainerRef.createComponent<any>(componentFactory);
    
  

还有这样的 HTML:

<ng-template componentLoader>
                
</ng-template>

现在从网格组件中,我只需为要添加到网格的每个组件调用 ComponentLoader,因此网格 html 将如下所示:

<div     
   *ngIf=" gridItem.components && gridItem.components.length > 0"
   class="component-container"
>
       <component-loader
         *ngFor="let component of gridItem.components"
         [component]="component">

        </component-loader>
</div >

现在组件正在正确加载,无论如何我仍然不知道我之前缺少什么。

【讨论】:

以上是关于Angular - 使用自定义指令加载多个组件返回未定义的主要内容,如果未能解决你的问题,请参考以下文章

Angular - 加载图像 src 后的自定义指令

Angular 2 在 3rd 方指令中使用自定义组件选择器

错误多个指令 [bar, bar] 在使用自定义指令和 angular-bootstrap 时要求模板

Angular 2+将指令传递给自定义组件

angular2采用自定义指令(Directive)方式加载jquery插件

TS中的Angular 2访问指令返回未定义