# All files / utils/src dynamic-component.service.ts

100% Statements 16/16
50% Branches 1/2
100% Functions 4/4
100% Lines 14/14

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77

    4x

    4x

    20x

    4x
    1x
    1x

    1x

    4x
    1x
    1x
    1x

    1x

    1x

    4x
     /**
     * Insert a component dynamically using a service
     *
     * ### Example
     * ```ts
     * import { DynamicComponentService } from './dynamic.component.service';
     * import { MyDynamicComponent } from './my-1.component';
     *
     * @Component({
     *   template: ` ... <div #dymamic></div>`
     * })
     * export class MyComponent {
     *   @ViewChild('dynamic', {read:ViewContainerRef}) vcr: ViewContainerRef;
     *
     *   constructor(public dcs: DynamicComponentService) {}
     *
     *   insertComp() {
     *     let compRef = this.dcs.createComponent(MyDynamicComponent, this.vcr);
     *     ths.dcs.insertComonent(cmpRef);
     *     compRef.instance.items = [1,2,3];              // dealing with @input
     *     compRef.instance.output$.subscribe(val => {}); // dealing with @output
     *   }
     * }
     * ```
     */
    import {
      Component,
      ComponentFactoryResolver,
      ComponentRef,
      Inject,
      Injectable,
      ReflectiveInjector,
      ViewContainerRef
    } from '@angular/core';

    /**
     * Provide service to add or remove component dynamically
     */
    @Injectable()
    export class DynamicComponentService {
      /** used to create a factory from a component class */
      factoryResolver: ComponentFactoryResolver;
      /** defines where a dynamic components insert into */
      rootViewContainer: ViewContainerRef;

      constructor(@Inject(ComponentFactoryResolver) factoryResolver) {
        this.factoryResolver = factoryResolver;
      }

      /**
       * returns component reference
       * The reason to seperate `createCompnent` and `insertComponent` is
       * to allow some actions before we insert into a hostView.
       * e.g styling, setting attributes, etc
       */
      createComponent(component: any, into?: ViewContainerRef): ComponentRef<any> {
        this.rootViewContainer = into || this.rootViewContainer;
        const factory = this.factoryResolver.resolveComponentFactory(component);

        return factory.create(this.rootViewContainer.parentInjector);
      }

      /**
       * insert component
       */
      insertComponent(componentRef: ComponentRef<any>): Component {
        const compId = `ngui-dyn-${Math.floor(Math.random() * 10 ** 7) + 10 ** 6}`;
        componentRef.location.nativeElement.setAttribute('id', compId);
        componentRef.instance.id = compId;

        this.rootViewContainer.insert(componentRef.hostView);

        return componentRef.instance;
      }

    }