在结构指令中访问组件实例

时间:2019-05-15 16:14:53

标签: angular typescript angular-directive

我有一个结构指令,我需要访问已应用该指令的组件的实例。

存在一个未解决的问题,很少有选项/ hack适用于普通指令,但不适用于结构化指令。

https://github.com/angular/angular/issues/8277

1 个答案:

答案 0 :(得分:0)

您不能像这样将组件添加到另一个组件中-但是您可以动态地调用它们。

附加的是通过指令构建动态组件的实际示例。最终,这就是我想您想要的。但是,您不能级联组件-这是行不通的。我发表了一些评论,以便您了解发生了什么,另一件事是,当您执行此路线时,您将必须转到本地模块并为输入组件添加一行。

import { footerComponent } from './../../uicomponents/footer/footer.component';
import { headerComponent } from './../../uicomponents/header/header.component';
import { cssloaderComponent } from './../../uicomponents/cssloader/cssloader.component';

// tslint:disable-next-line:max-line-length
import { Directive, Input, OnInit, ViewContainerRef, AfterViewInit, OnDestroy, ComponentFactoryResolver, OnChanges } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { Subject, Observable, from } from 'rxjs';
import { filter } from 'rxjs/operators';
import { viewsdataservice } from 'src/app/services/viewsdata.service';
import { contentoutletComponent } from 'src/app/uicomponents/contentoutlet/contentoutlet.component';

@Directive({
  selector: '[pagebuilderdirective]'
})
export class pagebuilderDirective implements OnInit, OnDestroy, AfterViewInit, OnChanges {
  @Input() pagebuilderdirective: Observable<any>;
  private onDestroy$ = new Subject<boolean>();
  components;
  route0$;

  private elRef: any;

  readonly templateMapper = {
    css: cssloaderComponent,
    contentoutlet: contentoutletComponent,
    header: headerComponent,
    footer: footerComponent
  };

  constructor(
    public viewContainerRef: ViewContainerRef,
    private factory: ComponentFactoryResolver,
    private router: Router,
    private vds: viewsdataservice
*********we created a view data service to connect to google firebase/firestore to get our particular data - we subscribe to the data and use it. ********
  ) {
    this.elRef = viewContainerRef;
    router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
        this.pagebuilderdirective.subscribe(data => {
          if (data) {
            this.loadComponent(data);
          }
        });
      }
    });
  }

  ngOnInit(): void {


  }

  ngOnChanges() {
  }

  ngOnDestroy() {
    this.elRef.clear();
  }

  ngAfterViewInit() {

    this.pagebuilderdirective.subscribe(data => {
      if (data) {
        this.loadComponent(data)
      }
    });
  }

  checker() {
    return this.pagebuilderdirective;
  }

  loadComponent(data: any) {
    this.elRef.clear();

    const route0 = this.vds.route_arr;
    const components: Array<any> = data[0].components;

    const componentmanifest=this.vds.flatten(data[0].componentsmanifest);
     ***** we found that it was easier to write a service that flattens our array, you probably won't need this. *******
    const orgdata = data[0];
    if (components) {
      const filtered = from(components).pipe(
        filter(component => {
          if (
            component.published === true && componentmanifest.pagespublished === route0 || component.da === "pb") {
              return component;
*****we set a boolean on our components and create a manifest (array of actual components and where they go to, the final indicator was if it was a parent component or child, we did this speficially so we could segment components down to page and subcomponent(child components) and assign that data to them. If you don't do this, any components listed (assuming one has multiple directives, will generate or kick an error)******
          } 
        })
      );

      filtered.subscribe(
        (component) => {
        const componentFactory = 
******component factory is your friend here, we call the components via name to match the entry components ********
this.factory.resolveComponentFactory(this.getComponentByAlias(component.name));
        // this.elRef.clear();
        const componentRef = this.elRef.createComponent(componentFactory);
        (<any>componentRef.instance).data = orgdata;
      });
    }
    // this.elRef.clear();
  }

  private getComponentByAlias(alias: string) {
    return this.templateMapper[alias];
  }
相关问题