I have been trying to find a solution for this everywhere.
I have a project with different 'skins', which are basically different sets of templates/Css.
I am trying to have my components use the skin based on a variable THEME_DIR.
Unfortunately, I cannot find how to make that happens. I looked into the Dynamic Component Loader on angular.io without success.
I also looked at a few answers here without success either.
Does anyone have an idea?
This is what I tried so far:
import { ComponentFactoryResolver, ViewContainerRef } from '@angular/core';
// @Component({
// templateUrl: '../../assets/theme/'+THEME_DIR+'/login.template.html',
// })
export class LoginComponent implements, AfterViewInit {
private log = Log.create('LoginPage');
constructor(private mzksLsRequestService: MzkLsRequestService,
private componentFactoryResolver: ComponentFactoryResolver,
public viewContainerRef: ViewContainerRef) {
}
ngAfterViewInit() {
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(new Component({
templateUrl: '../../assets/theme/default/login.template.html',
}));
let viewContainerRef = this.viewContainerRef;
viewContainerRef.clear();
let componentRef = viewContainerRef.createComponent(componentFactory);
}
}
According to Angular, when you have a complex view (i.e. a view with more than 3 lines), then go with templateUrl (use external file); otherwise, use the template (inline HTML) properly of the component decorator.
When we define the template in an external file and then after we link with our component is said to be an external template. In other words, The External templates define the HTML code in a separate file and we can refer to that file using templateURL property of Component decorator.
You can simply extend your base component and overwrite the template. This allows you to have different components with the exact same functionality, but different templates.
Components meaning a piece of data that can be used in multiple places and can be rendered anywhere on the page. Essentially a free way of designing a web page without needing a developer's intervention. Page Templates meaning a much more rigid design of the pages that will prevent possible design complications.
I had the problem when trying to load dynamicaly templates from the server (i wanted to make security check, translation on server side before serving html.
I've solved it after changing webpack config. In fact, after doing ng eject
, it created a webpack.config.js which contains a .ts loader @ngtools/webpack
and :
new AotPlugin({
"mainPath": "main.ts",
"replaceExport": false,
"hostReplacementPaths": {
"environments\\environment.ts": "environments\\environment.ts"
},
"exclude": [],
"tsConfigPath": "src/main/front/tsconfig.app.json",
"skipCodeGeneration": true
})
This last one, is the origin of the problem. It concerns the AOT (Ahead Of Time). According to the documentation : ngtools on the options section, it's mentionned :
skipCodeGeneration. Optional, defaults to false. Disable code generation and do not refactor the code to bootstrap. This replaces templateUrl: "string" with template: require("string")
If you dont want your templateUrl to be compiled AOT, i recommand you to remove the AotPlugin, and to use of the ts-loader instead of @ngtools/webpack see :
ts-loader
The rule for ts will look like this :
{
test: /\.tsx?$/,
loader: 'ts-loader'
}
Now you can load fresh templates from a relative URL on demand. Example :
@Component({
selector : "custom-component",
templateUrl : "/my_custom_url_on_server"
})
export class CustomComponent {
}
See Issue
As of Ivy (I think) we can use static variables (for example enviroment) in templateUrl. for example:
import { environment } from 'src/environments/environment';
@Component({
selector: 'home',
templateUrl: `./skins/${environment.skin}/home.page.html`,
styleUrls: ['./skins/${environment.skin}/home.page.scss']
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With