15
 @Component({
  selector: 'bancaComponent',
  templateUrl: '{{str}}'
})
export class BancaComponent implements OnInit {
  str: String;
  constructor(private http: Http) { }
  ngOnInit(): void {
  this.str = "./file.component.html";
}

Is there another way to make it ? Thanks :)

Boulboulouboule
  • 4,087
  • 1
  • 13
  • 29
Dell
  • 237
  • 2
  • 6
  • 13

2 Answers2

16

Try this solution :

import
{
    Compiler, Component, Injector, ViewChild, NgModule, NgModuleRef,
    ViewContainerRef, AfterViewInit, OnInit
} from '@angular/core';

@Component({
    selector: 'bancaComponent',
    template: `<ng-container #dynamicTemplate></ng-container>`
    // or with a templateUrl
})
export class BancaComponent implements AfterViewInit, OnInit
{
    @ViewChild('dynamicTemplate', { read: ViewContainerRef }) dynamicTemplate;

    constructor(
        private _compiler: Compiler,
        private _injector: Injector,
        private _m: NgModuleRef<any>)
    {
    }

    ngAfterViewInit()
    {
        let myTemplateUrl = './file.component.html';

        if (MYCONDITION === MAEXPECTATION)
        {
            myTemplateUrl = './another-template.component.html';
        }

        const tmpCmp = Component({
            moduleId: module.id, templateUrl: myTemplateUrl
        })(class { });
        
        const tmpModule = NgModule({ declarations: [tmpCmp] })(class { });

        this._compiler.compileModuleAndAllComponentsAsync(tmpModule)
            .then((factories) =>
            {
                const f = factories.componentFactories[0];
                const cmpRef = f.create(this._injector, [], null, this._m);
                cmpRef.instance.name = 'dynamic';
                this.dynamicTemplate.insert(cmpRef.hostView);
            });
    }
}

Inspired from : Angular 2/4 component with dynamic template or templateUrl

Official source : https://angular.io/guide/dynamic-component-loader

olfek
  • 3,210
  • 4
  • 33
  • 49
Boulboulouboule
  • 4,087
  • 1
  • 13
  • 29
  • It's edited with a variable and a condition example ;) – Boulboulouboule Nov 06 '17 at 09:40
  • 1
    What is the error ? Take a look at the angular official solution for this kind of problem : https://angular.io/guide/dynamic-component-loader – Boulboulouboule Nov 06 '17 at 10:04
  • 3
    @Boulboulouboule I'm working on Angular 5 and it gives me following error --- ERROR in ./src/app/app.component.ts Module not found: Error: Can't resolve ' myTemplateUrl' – ranjit redekar May 03 '18 at 10:28
  • 1
    was anyone able to resolve the error in angular 5+ versions? – prabhat gundepalli Nov 06 '18 at 20:59
  • @Boulboulouboule, you are a gem. – Kashif Nazar Dec 03 '18 at 05:50
  • @prabhatgundepalli - I got the same error on Angular 6. Strangely, shorthand property structuring worked for me. ```const templateUrl: string = this.getTemplateUrl(); { moduleId: module.id, templateUrl }``` – Kashif Nazar Dec 03 '18 at 05:54
  • I was able to get this partially working on Angular 7 - thanks for your help. However, I don't seem to be able to get any sort of directives working or property bindings in the new template. I get the error: "ERROR Error: Uncaught (in promise): Error: Template parse errors: Can't bind to 'ngForOf' since it isn't a known property of 'p'." Is it possible to get these working? Also seems to strip out any – azsl1326 Dec 23 '18 at 05:41
  • **** UPDATE: Importing BrowserModule seems to fix the structural directive and property bindings issue - NgModule({ imports: [BrowserModule], ......... – azsl1326 Dec 23 '18 at 06:14
  • @KashifNazar Can you expand upon how you got rid of the Module error? It has started to appear for me and I am not sure how to get rid of it. Thanks! – azsl1326 Dec 24 '18 at 01:39
  • It complains when I put a variable in the template pathas it seems it doesn't find the right path .Is there anything extra I need to do ? – Amit Nair Feb 05 '19 at 07:52
  • @Boulboulouboule I am getting thiserror error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig – Debashish Dwivedi Apr 04 '19 at 06:48
  • Has anyone figured this out? @azsl1326 that didn't work –  Aug 21 '19 at 11:55
  • 1
    getting this error with angular 9: https://www.screencast.com/t/HgRuD3fKD – Nimesh khatri Jul 14 '20 at 09:13
  • 2
    First I got `Error: Angular JIT compilation failed: '@angular/compiler' not loaded!`. I fixed it by `import "@angular/compiler";`. Then I got `Error: Component '' is not resolved: templateUrl: ./another-template.component.html. Did you run and wait for resolveComponentResources()'?`. I can't find how to import / use `resolveComponentResources`. Could you please advise? – Halfist Feb 10 '21 at 10:16
  • There should be a working solution for this in 2021, anyone got any? – DARKGuy Jul 25 '21 at 06:02
0

Angular 13

Create multiple components with the desired templates, then load the components in dynamically like so:

@Component({
    selector: 'app',
    template: `<ng-template #dynamic></ng-template>`
})
export class AppComponent implements AfterContentInit
{
    @ViewChild('dynamic', { static: true, read: ViewContainerRef })
    public dynamicContainer: ViewContainerRef;

    ngAfterContentInit()
    {
        const myComponentInstance = this.dynamicContainer.createComponent(MyComponent);
    }
}

source

olfek
  • 3,210
  • 4
  • 33
  • 49