Dynamic Route Loading in Angular 2 Fails. (Beta)

点点圈 提交于 2019-12-01 01:16:52

TypeScript compiles imports into javascript in a certain way, you can try something like this to be able to use eval() (cringe). This obviously won't work if typescript compiles differently, but it is fun to check out if this works any ways :)

for (let i = 0; i < data.length; i++) {
  this.routeConfigArray.push({ //routeConfigArray : RouteDefinition
    path: data[i].path,
    name: data[i].name,
    component: getComponent(data[i].component)
  });
  this._router.config(this.routeConfigArray);   
}

function getComponent(comp : string) : Function {
    //convert camelCase to underscore notation
    let component : string = comp;
    component = component[0].toLowerCase() + component.slice(1);
    component = component.replace(/([A-Z])/g, function(match) {
        return '_' + match.toLowerCase();
    });
    component += '_1';
    return eval(component[comp])
}

ADDENDUM

As addition to your own solution with using a AsyncRoute, I believe you actually got quite a good solution going on. Perhaps if you place all the pages in a certain way, you can extract the resource location from the path, but that is not necessary. (i mean to get from the path string /about to the resource string ./app/about/about.component shouldn't be hard with a small algorithm. But that might be something for an update.

Anyways, you can try something like this with the AsyncRoute

warning: untested code ahead

let routes : any[] = [
    { "path" : "/about" , "name" : "About" , "component" : "AboutComponent", "route": "/About" , "resource" : "./app/about/about.component" },
    { "path" : "/contact" , "name" : "Contact" , "component" : "ContactComponent", "route": "/Contact" , "resource" : "./app/contact/contact.component" }
];

routes.forEach((route : any) => {
    this.routeConfigArray.push(
        new AsyncRoute({
            path : route.path,
            loader : () => System.import(route.resource).then(m => m[route.component]),
            name : route.name
        })
    );
});

this._router.config(this.routeConfigArray);

You are too good @PierreDuc , i was just looking at regex to build the same function, some edits i would like to point out to bring it in working state....

for (let i = 0; i < data.length; i++) {
  this.routeConfigArray.push({ //routeConfigArray : RouteDefinition
    'path': data[i].path,
    'name': data[i].name,
    'component': getComponent(data[i].component).constructor
  });
  this._router.config(this.routeConfigArray);   
}

function getComponent(comp : string) : Function {
    //convert camelCase to underscore notation
    let component : string = comp;
    component = component[0].toLowerCase() + component.slice(1);
    component = component.replace(/([A-Z])/g, function(match) {
        return '_' + match.toLowerCase();
    });
    component += '_1.';
    return eval("new "+component+comp+"()")
}

Thankyou once again dude, its now in a running mode!!! Phew!

Thierry Templier

You could use the another approach that the one from @Pierre and @Pratik based on a method that returns the name of classes:

Object.prototype.getName = function() { 
  var funcNameRegex = /function (.{1,})\(/;
  var results = (funcNameRegex).exec((this).constructor.toString());
  return (results && results.length > 1) ? results[1] : "";
};

In your component you can then configure your routes dynamically like this:

ngOnInit() {
  this.routes = [
    {
      path: '/test', component: 'OtherComponent', name: 'Test'
    }
  ];
  this.configureRoutes(this.routes);
  this.router.config( this.routes);
}

configureRoutes(routes) {
  var potentialComponents = [ OtherComponent ];
  routes.forEach((route) => {
    route.component = potentialComponents.find((component) => {
      return component.name === route.component;
    });
  });
}

This requires to know by advance potential components that can be involved in routing.

See this plunkr for demo: https://plnkr.co/edit/KKVagp?p=preview.

See this question:

Update to the first above scenario : The above dynamically loads routes on the UI, but for that to happen i do have to mention it in my AppComponent

import {AboutComponent} from '/path';
import {ContactComponent} from '/path';

//and then either include it in a directive or mention The component Name some place in the code

But this defeats the purpose 'Dynamic Loading', as i have to know which components would be requested and also cannot lazy load them. Say i do that for 500 components, i have to load these 500 components and then just from a JSON mentioned above i pick which has to be loaded on the UI.

Solution(Completed And Tested) ==> I now do not have to mention the components i want to load in any import statement neither in any Directive. Thererby making it lazy loading and Completely Dynamic

How By Using AsyncRoute Class.

Here's my new JSON
//"route" is to map it to [routerLink]="['/Home']" & "resource" is the actual path of component

 [
  { "path" : "/about" , "name" : "About" , "component" : "AboutComponent", "route": "/About" , "resource" : "./app/about/about.component" },
  { "path" : "/contact" , "name" : "Contact" , "component" : "ContactComponent", "route": "/About" , "resource" : "./app/about/about.component" },
  { "path" : "/blog" , "name" : "Blog" , "component" : "AboutComponent", "route": "/About" , "resource" : "./app/about/about.component" },
  { "path" : "/news" , "name" : "News" , "component" : "AboutComponent", "route": "/About" , "resource" : "./app/about/about.component" }
]

Now to the code, here i fetch this JSON and add it to the routeConfigArray : RouteDefinition[] and call the Router's .config(routeConfigArray)

  let routes : any[] = data; // consist the json data in array


routes.forEach((route : any) => {
        this.routeConfigArray.push(
            new AsyncRoute({
                path : route.path,
                loader : () => System.import(route.resource).then(m => m[route.component]),
                name : route.name
            })
        );
    });

    this._router.config(this.routeConfigArray);

And thats how it works!!!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!