3

I am developing an ecommerce application, and one major feature is that this app should have multiple themes. The total number of themes could be 100 or even more. However, these themes all have the same data (For example: all home page have same banner images, new product, feature product data.) .

I know I can use ng-template or TemplateRef to determine which piece of HTML should display. But since I have over 100 themes, both ng-template or TemplateRef methods will load a lot of extra files. So I think I need some sort of lazy load, when a component loads the data then lazy loads the correct HTML template. So how can I have this work?

Idea structure

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Jack Sun
  • 2,012
  • 1
  • 16
  • 20
  • Instead of entirely new templates, could you theme using the CSS? If so, there is a walk through here: https://www.freecodecamp.org/news/how-to-create-themes-for-your-angular-7-apps-using-css-variables-69251690e9c5/ – DeborahK Jul 23 '21 at 20:08
  • 1
    Does this answer your question? [One Component Multiple Templates based on Condition](https://stackoverflow.com/questions/37634724/one-component-multiple-templates-based-on-condition) – Heretic Monkey Jul 23 '21 at 21:05
  • see this:https://therichpost.com/how-to-include-html-file-in-angular-12-component/ – Therichpost Jul 24 '21 at 06:22
  • This is a really good question, you want to "lazy load" a module with all the components based on user selection at runtime. There is a method on the angular router called `resetConfig` you might be able to use that with a route config which specifies lazy loading the particular module... I'm going to try to set up a project demonstrating this. – Aviad P. Jul 24 '21 at 19:18
  • 1
    Don't vote to close on duplicate, he's asking a different question, he's asking about lazy loading a set of components. The candidate duplicate doesn't talk about lazy loading. – Aviad P. Jul 24 '21 at 20:32
  • @AviadP. In my case, I have to load the components with data anyway. The ideal way for me is that lazy load ONE selected HTML & CSS template after the a component is loaded. So far, I know how to lazy load a Module without routing. However, I am seeking a better way to do it. – Jack Sun Jul 25 '21 at 04:40
  • I don't understand your comment, what do you mean load components with data? A component is a class and a template (and css) - no data involved. The data comes from services in the application. My solution does use routing, don't you need routing? - My solution only loads ONE module with one set of components inside it. – Aviad P. Jul 25 '21 at 04:42
  • @HereticMonkey As I said, I know how to use ng-template, but this does not solve my problem. This project has many themes, and I am looking for a solution to load as few files as possible. – Jack Sun Jul 25 '21 at 04:44
  • @AviadP. You are totally right. I need to pass data to selected HTML template. I have too many themes. I don't want to create 100 extra components to load same data from service or create a huge HTML file with 100 ng-template. So far, thanks for your help. – Jack Sun Jul 25 '21 at 04:50
  • You have no choice but to create a component for each theme (unless you use css to style them) - HOWEVER, you don't have to load all 100's of components at start, that's what my solution does, it allows you to select which particular set of components you want to load, so the client remains thin – Aviad P. Jul 25 '21 at 05:02
  • 1
    @AviadP. If you have a clarification to make to the question, [edit] the question with that clarification, rather than simply saying “don’t vote to close”. In other words, make the question not a duplicate by editing the question, not just complaining. – Heretic Monkey Jul 25 '21 at 15:20
  • Same advice goes to the OP of course, and is included in the [help center article about duplicates](https://stackoverflow.com/help/duplicates). – Heretic Monkey Jul 25 '21 at 15:24

3 Answers3

1

Looks like it is possible, all our routes are handled by lazy loaded modules. This is our out-of-the-box route config:

const routes: Routes = [
  { path: '', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
];

While module lazy has this route config:

const routes: Routes = [
  { path: 'home', component: HomeComponent },
]

While HomeComponent is taken from the declarations of module lazy.

Then define another module, called for example lazy-two with the same route config, and its own HomeComponent.

Finally, you can switch between the modules by using this code:

lazyLoad() {
  const routes: Routes = [
    { 
      path: '', 
      loadChildren: () => import('./lazy-two/lazy-two.module')
                            .then(m => m.LazyTwoModule)
    }
  ];

  this.router.resetConfig(routes);
  this.router.navigateByUrl('/home');
}

This will lazy load module lazy-two and refresh the route to /home - you will see the component of the new module displayed.

I couldn't create a stackblitz, some errors occurred probably because of lazy loading. So I ran it locally on my machine and pushed the code to GitHub

EDIT I managed to make a StackBlitz

Aviad P.
  • 32,036
  • 14
  • 103
  • 124
0

I recommend used ComponentFactoryResolver to create the components that you need to render.

this.templates = [
  {
    id: "template-1",
    component: Template1,
  },
  {
    id: "template-2",
    component: Template2,
  },
];

  ngOnInit() {
    this.templates.forEach((element) => {
      this.containerReference.createComponent(
        this.factoryResolver.resolveComponentFactory(element.component)
      );
    });
  }

in the .html you should have

<ng-container #containerReference><ng-container>
0

what about using the same component and styling it different when you select the template?