如何在Angular 5中使用路由实现动态组件?

时间:2019-05-10 12:39:55

标签: angular dynamic routes components

我正在尝试构建一个应用程序,其中某些部分是从动态模板派生的,并且我希望允许该组件进行路由。

// Object received from API
class ComponentModel {
    public name: string;
    public template: string;
    public styles: string [];
    public path: string;
    public outlet: string;
}
// Classes to store information about component
class ComponentInfo {
    public model: ComponentModel;
    public component: any;
    public isRoute: boolean;
    public isHome: boolean;
    public componentReference: ComponentRef<any>;
    public factory: ComponentFactory<any>;
}

// A map for all components created (to be used as a cache)
ComponentMap: Map<string, ComponentInfo> = new Map<string, ComponentInfo>();
// The container to show dynamic component
@ViewChild('dynamicContainer', { read: ViewContainerRef }) public dynamicContainer: ViewContainerRef;

// Create a component and all of his dependencies
public createComponentAndDependencies(model: ComponentModel, mainPage: boolean = false): any[] {
    let ret = [];
    var nComponent = Component({ template: model.template, styles: model.styles, selector: model.name, mainPage: mainPage })( class {} );
    ret[ret.length] = nComponent;
    this.ComponentMap.set(model.name, { model: model, component: nComponent } as ComponentInfo);
    model.componentDependecies.forEach(dependency => { ret = ret.concat(this.createComponentAndDependencies(dependency)); });
    return ret;
}

// main method, called after receive a component from API
public createComponentAndCompile(component: ComponentModel) {
    try {
        this.dynamicItemView.clear();
        this.ComponentMap.clear();
        const newComponents = this.createComponentAndDependencies(component, true);

        const module = NgModule({
            imports: [RouterModule],
            declarations: newComponents,
            entryComponents: newComponents,
        })(class { });

        let cp = this.compiler.compileModuleAndAllComponentsAsync(module);
        cp.then((factories) => {
            factories.componentFactories.forEach(componentFactory => {
                let cpName = componentFactory.selector.toString();
                let cpInfo = this.ComponentMap.get(cpName);
                cpInfo.factory = componentFactory;
                cpInfo.componentReference = componentFactory.create(this.injector, [], null, this.moduleRef);
                cpInfo.componentReference.instance.name = cpName;
                this.activatedRoute.routeConfig.children.push({
                    path: cpInfo.model.path,
                    component: cpInfo.componentReference.instance,
                    outlet: cpInfo.model.outlet
                } as Route);
                if (cpInfo.mainPage)
                    this.dynamicItemView.insert(cpInfo.componentReference.hostView);
            });

            this.router.events.subscribe(async re => {
                console.log(re.toString());
            });
        });
    } catch (error) {
        this.notificationService.showError(error.message);
    }
}

我动态地添加了路线

 this.activatedRoute.routeConfig.children.push({
                    path: cpInfo.model.path,
                    component: cpInfo.componentReference.instance,
                    outlet: cpInfo.model.outlet
                } as Route);

运行代码时,将正确创建并显示该组件,但是当我使用模板导航(即:<a [routerLink] = "['something', {outlets: {home: 'component1'}} }] "> Component 1 </a>)时,将显示以下错误:"NavigationError(id: 2, url: 'something(home:component1)', error: Error: No component factory found for component1. Did you add it to @NgModule.entryComponents?)"

我在ngModule上插入了entryComponents,但仍然无法正常工作。

        const module = NgModule({
            imports: [RouterModule],
            declarations: newComponents,
            entryComponents: newComponents,
        })(class { });

怎么了?

0 个答案:

没有答案