Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 动态创建组件的角度获取viewContainerRef_Angular_Dynamic_Components - Fatal编程技术网

Angular 动态创建组件的角度获取viewContainerRef

Angular 动态创建组件的角度获取viewContainerRef,angular,dynamic,components,Angular,Dynamic,Components,在组件中,我确实使用服务加载JSON数据。根据树状结构的数据,我希望动态创建新组件: import { Component, AfterViewInit, OnDestroy, ComponentFactoryResolver, ViewContainerRef, Input, ViewChild } from '@angular/core'; import { MenuComponent } from '../menu/menu.component'; import { RowCompone

在组件中,我确实使用服务加载JSON数据。根据树状结构的数据,我希望动态创建新组件:

import { Component, AfterViewInit, OnDestroy, ComponentFactoryResolver, ViewContainerRef, Input, ViewChild } from '@angular/core';

import { MenuComponent } from '../menu/menu.component';
import { RowComponent } from '../row/row.component';

import { DynamicComponentInterface } from '../../interfaces/dynamicComponentInterface';
import { SlotDirective } from './slot.directive';

import { ContentService } from '../../services/content.service';
import { DynamicComponentsHostService } from '../../services/dynamicComponentsHost.service';



@Component({
  selector: 'app-slot',
  templateUrl: './slot.component.html',
  styleUrls: ['./slot.component.css']
})
export class SlotComponent implements AfterViewInit, OnDestroy  {
  @Input() id:number;
  @ViewChild(SlotDirective) slot: SlotDirective;
  private slotDataTree;
  private componentRef;
  private contentReadySubscription;

  constructor(
    private contentService : ContentService,
    private componentFactoryResolver : ComponentFactoryResolver,
    private viewContainerRef: ViewContainerRef,
    private dynamicComponentsHostService: DynamicComponentsHostService

  ) {

  }

  ngAfterViewInit(){
    // get JSON data with TreeStructure from Service
    if(this.contentService.stateReady){
      this.slotDataTree = this.contentService.getCurrentBySlotId(this.id);
      this.renderContentTree();
    }
    else{
      this.contentReadySubscription = this.contentService.getCurrentPageContentReadyObserver().subscribe(stateReady => {
    if(stateReady ){
      this.slotDataTree = this.contentService.getCurrentBySlotId(this.id);
      this.renderContentTree();
    }
      });
    }
  }

  renderContentTree(){
    if(this.slotDataTree){


      let componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.dynamicComponentsHostService.getDynamicComponentType(this.slotDataTree.type));
      let viewContainerRef = this.slot.viewContainerRef;
      let componentRef = viewContainerRef.createComponent(componentFactory);


      (<DynamicComponentInterface>componentRef.instance).data = this.slotDataTree;

    // Works like a charm.
    // now I want to create children for the newly created component
    // so I need the viewContainerRef of componentRef



    // this delivers a viewRef
      console.log(componentRef.hostView);

    // this delivers sometimes a viewContainerRef in console, but a comile error that _viewRef does not exists

      console.log(componentRef._viewRef._viewContainerRef);

    // I cannot do this in the dynamicly rendered components class its self, because of circular dependencies that would occour then
      /*
      if(this.slotDataTree.children.length){
    for(var i = 0; i < this.slotDataTree.children.length; i++){

      let componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.dynamicComponentsHostService.getDynamicComponentType(this.slotDataTree.children[i].type));
      let viewContainerRef = componentRef._viewRef._viewContainerRef;
      let componentRef = viewContainerRef.createComponent(componentFactory);

    }
      }
      */
      if(this.contentReadySubscription){
    this.contentReadySubscription.unsubscribe();
      }
    }
  }

  ngOnDestroy() {
    if(this.contentReadySubscription){
      this.contentReadySubscription.unsubscribe();
    }
  }
}
import{Component,AfterViewInit,ondestory,ComponentFactoryResolver,ViewContainerRef,Input,ViewChild}从'@angular/core'导入;
从“../menu/menu.component”导入{MenuComponent};
从“../row/row.component”导入{RowComponent};
从“../../interfaces/DynamicComponentInterface”导入{DynamicComponentInterface};
从“/slot.directive”导入{SlotDirective};
从“../../services/content.service”导入{ContentService};
从“../../services/dynamicComponentsHost.service”导入{DynamicComponentsHostService};
@组成部分({
选择器:“应用程序插槽”,
templateUrl:'./slot.component.html',
样式URL:['./slot.component.css']
})
导出类SlotComponent实现AfterViewInit、OnDestroy{
@Input()id:number;
@ViewChild(SlotDirective)插槽:SlotDirective;
私有时隙数据树;
私有组件参考;
私有内容易订阅;
建造师(
私有contentService:contentService,
专用componentFactoryResolver:componentFactoryResolver,
私有viewContainerRef:viewContainerRef,
专用dynamicComponentsHostService:dynamicComponentsHostService
) {
}
ngAfterViewInit(){
//从服务获取具有树状结构的JSON数据
if(this.contentService.stateReady){
this.slotDataTree=this.contentService.getCurrentBySlotId(this.id);
this.renderContentTree();
}
否则{
this.contentReadySubscription=this.contentService.getCurrentPageContentReadyObserver().subscribe(stateReady=>{
如果(状态就绪){
this.slotDataTree=this.contentService.getCurrentBySlotId(this.id);
this.renderContentTree();
}
});
}
}
renderContentTree(){
if(此.slotDataTree){
让componentFactory=this.componentFactoryResolver.resolveComponentFactory(this.dynamicComponentsHostService.getDynamicComponentType(this.slotDataTree.type));
让viewContainerRef=this.slot.viewContainerRef;
让componentRef=viewContainerRef.createComponent(componentFactory);
(componentRef.instance).data=this.slotDataTree;
//工作起来很有魅力。
//现在我想为新创建的组件创建子级
//所以我需要componentRef的viewContainerRef
//这将提供一个viewRef
日志(componentRef.hostView);
//这有时会在控制台中传递viewContainerRef,但不存在_viewRef的滑稽错误
日志(componentRef.\u viewRef.\u viewContainerRef);
//我不能在动态呈现的组件类中自己做这件事,因为循环依赖性会在那时发生
/*
if(this.slotDataTree.children.length){
for(var i=0;i
我可以动态创建组件。但我也知道如何创建子组件到已创建的组件。意味着我需要刚创建的组件的viewRefContainer

由于循环依赖关系,我无法在components类中创建dynamicly组件,该类由dynamicly创建

我怎样才能解决这个问题


谢谢

我现在就是这样解决的。首先,我使用根组件,它是动态创建的组件树的原点。也许一个服务会更好:

import { Component, AfterViewInit, OnDestroy, OnInit, ComponentFactoryResolver, Input, ViewChild, ChangeDetectorRef } from '@angular/core';
import { MenuComponent } from '../menu/menu.component';
import { DynamicComponent } from '../dynamic/dynamic.component';
import { SlotDirective } from '../../directives/slot.directive';
import { ContentService } from '../../services/content.service';
import { EditService } from '../../services/edit.service';
import { DynamicComponentsHostService } from '../../services/dynamicComponentsHost.service';
import { DynamicComponentsData } from '../../classes/dynamicComponentsData';

@Component({
  selector: 'app-slot',
  templateUrl: './slot.component.html',
  styleUrls: ['./slot.component.css']
})
export class SlotComponent implements OnDestroy, OnInit  {
  @Input() id:number;
  @ViewChild(SlotDirective) slot: SlotDirective;
  private componentRef;
  private contentReadySubscription;
  public slotDataTree : DynamicComponentsData = new DynamicComponentsData({},false);

  constructor(
    protected contentService : ContentService,
    private editService : EditService,
    private componentFactoryResolver : ComponentFactoryResolver,
    private dynamicComponentsHostService: DynamicComponentsHostService
  ) {
  }

  ngOnInit(){
    var slotData;
    if(this.contentService.stateReady){
      if( slotData = this.contentService.getCurrentBySlotId(this.id) ){
        this.slotDataTree = slotData;
      }
      else{
        this.slotDataTree.type = 'none';
      }
      this.renderContentTree();
    }

    this.contentReadySubscription = this.contentService.getCurrentPageContentReadyObserver().subscribe(stateReady => {
      if(stateReady ){
        if( slotData = this.contentService.getCurrentBySlotId(this.id) ){
          this.slotDataTree = slotData;
        }
        else{
          this.slotDataTree.type = slotData;
        }
        this.renderContentTree();
      }
    });

    DynamicComponentsData.changed.subscribe( changeObject =>{
      this.renderContentTree();
    });
  }

  renderChilds(viewContainerRef,childs){
    for(var i = 0; i < childs.length; i++){
      // create the dynamic component. Use a service to get the types
      let componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.dynamicComponentsHostService.getDynamicComponentType(childs[i].type).class);
      let componentRef = viewContainerRef.createComponent(componentFactory);
      // give some data
      (<DynamicComponent>componentRef.instance).data = childs[i];
      // subscribe an event emitter
      (<DynamicComponent>componentRef.instance).sendViewContainerRef.subscribe(
        (event:any)=>{
          if(event.childs){
            this.renderChilds(event.viewContainerRef, event.childs);
          }
        }
      );
    }
  }

  renderContentTree(){
    let viewContainerRef = this.slot.viewContainerRef;
    viewContainerRef.clear();

    if(this.contentService.getCurrentBySlotId(this.id)){
      this.renderChilds(this.slot.viewContainerRef, this.contentService.getCurrentBySlotId(this.id).children);
      if(this.contentReadySubscription){
        this.contentReadySubscription.unsubscribe();
      }
    }
  }

  ngOnDestroy() {
    if(this.contentReadySubscription){
      this.contentReadySubscription.unsubscribe();
    }
  }
}
import{Component,AfterViewInit,ondestory,OnInit,ComponentFactoryResolver,Input,ViewChild,ChangeDetectorRef}从'@angular/core'导入;
从“../menu/menu.component”导入{MenuComponent};
从“../dynamic/dynamic.component”导入{DynamicComponent};
从“../../directions/slot.directive”导入{SlotDirective};
从“../../services/content.service”导入{ContentService};
从“../../services/edit.service”导入{EditService};
从“../../services/dynamicComponentsHost.service”导入{DynamicComponentsHostService};
从“../../classes/DynamicComponentsData”导入{DynamicComponentsData};
@组成部分({
选择器:“应用程序插槽”,
templateUrl:'./slot.component.html',
样式URL:['./slot.component.css']
})
导出类SlotComponent实现OnDestroy,OnInit{
@Input()id:number;
@ViewChild(SlotDirective)插槽:SlotDirective;
私有组件参考;
私有内容易订阅;
public slotdata树:DynamicComponentsData=新的DynamicComponentsData({},false);
建造师(
受保护的contentService:contentService,
私有editService:editService,
专用componentFactoryResolver:componentFactoryResolver,
专用dynamicComponentsHostService:dynamicComponentsHostService
) {
}
恩戈尼尼特(){
var-slotData;
if(this.contentService.stateReady){
if(slotData=this.contentService.getCurrentBySlotId(this.id)){
this.slotDataTree=slotData;
}
否则{
this.slotDataTree.type='none';
}
this.renderContentTree();
}
this.contentReadySubscription=this.contentService.getCurrentPageContentReadyObserver().subscribe(stateReady=>{
如果(状态就绪){
if(slotData=this.contentService.getCurrentBySlotId(this.id)){
this.slotDataTree=slotData;
}
否则{
this.slotData.type=slotData;
}
this.renderContentTree();
}
});
DynamicComponentData.changed.subscribe(更改对象