1

In search of rendering MVC View in to angular 2 end up with this directive

export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> {
  const cmpClass = class DynamicComponent {};
  const decoratedCmp = Component(metadata)(cmpClass);

  @NgModule({ imports: [CommonModule, RouterModule], declarations: [decoratedCmp] })
  class DynamicHtmlModule { }

  return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule)
    .then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => {
      return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
    });
}

All working fine my View rendering as I wanted but after few seconds this Error pops.

enter image description here

my Component Code:

 import {
    Component,
    Directive,
    NgModule,
    Input,
    ViewContainerRef,
    Compiler,
    ComponentFactory,
    ModuleWithComponentFactories,
    ComponentRef,
    ReflectiveInjector, OnInit, OnDestroy, Type
} from '@angular/core';

import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { Http } from "@angular/http";
import 'rxjs/add/operator/map';

export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> {   
    const cmpClass = class DynamicComponent { };
    const decoratedCmp = Component(metadata)(cmpClass);

    @NgModule({ imports: [CommonModule, RouterModule], declarations: [decoratedCmp] })
    class DynamicHtmlModule { }

    return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule)
        .then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => {
            return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
        });
}

@Directive({ selector: 'mvc-partial' })
export class RenderingViewDynamic implements OnInit, OnDestroy {
    html: string = '<p></p>';
    @Input() url: string;
    cmpRef: ComponentRef<any>;

    constructor(private vcRef: ViewContainerRef, private compiler: Compiler, private http: Http) { }

    ngOnInit() {
        this.http.get(this.url)
            .map(res => res.text())
            .subscribe(
            (html) => {
                this.html = html;
                if (!html) return;

                if (this.cmpRef) {
                    this.cmpRef.destroy();
                }

                const compMetadata = new Component({
                    selector: 'dynamic-html',
                    template: this.html,
                });

                createComponentFactory(this.compiler, compMetadata)
                    .then(factory => {
                        const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
                        this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []);
                    });
            },
            err => console.log(err),
            () => console.log('MvcPartial complete')
            );

    }

    ngOnDestroy() {
        if (this.cmpRef) {
            this.cmpRef.destroy();
        }
    }
}

How could I over come this?

k11k2
  • 2,036
  • 2
  • 22
  • 36

1 Answers1

0

I believe the problem is that you define a method that returns Promise<ComponentFactory<any>>, however inside the method you use find function which can return undefined:

The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.

So that is what TS complains about. Just modify the method call:

createComponentFactory(...): `Promise<ComponentFactory<any>> | Promise<undefined>` { ... }

Same thing here:

this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []);
                    });

createComponent can only take ComponentFactory<C> but with your implementation it's possible that undefined can be passed. Maybe add a check that factory exists or if you're sure that it will never be undefined use non-null assertion operator.

Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • @MaximKorestskyi what you guess is right but your suggestion didn't resolve my issue same error occurs. Added my total code once check. – k11k2 Aug 22 '17 at 04:45
  • _but with your implementation it's possible that `undefined` can be passed_. Totally agreed . _Maybe add a check that factory exists_ what you mean ? – k11k2 Aug 22 '17 at 05:17
  • factory having value, not undefined. – k11k2 Aug 22 '17 at 05:32
  • @k11k2, `if (factory) { this.vcRef.createComponent( ....) }`. What do you expect to happen if you pass `undefined` into `createComponent`? – Max Koretskyi Aug 22 '17 at 05:35
  • target would be rendering my component with out exception so override that undefined make it smooth process. – k11k2 Aug 22 '17 at 05:53
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/152491/discussion-between-k11k2-and-maxim-koretskyi). – k11k2 Aug 22 '17 at 06:03