Angular 2 dynamic template url with string variable?
Try this solution :
import {
Compiler, Component, Injector, VERSION, 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
Angular 2/4 component with dynamic template or templateUrl
You can do it like this:
import {
Compiler, Component, Injector, VERSION, ViewChild, NgModule, NgModuleRef,
ViewContainerRef
} from '@angular/core';
@Component({
selector: 'my-app',
template: `
<h1>Hello {{name}}</h1>
<ng-container #vc></ng-container>
`
})
export class AppComponent {
@ViewChild('vc', {read: ViewContainerRef}) vc;
name = `Angular! v${VERSION.full}`;
constructor(private _compiler: Compiler,
private _injector: Injector,
private _m: NgModuleRef<any>) {
}
ngAfterViewInit() {
const tmpCmp = Component({
moduleId: module.id, templateUrl: './e.component.html'})(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.vc.insert(cmpRef.hostView);
})
}
}
Just make sure that the URL is correct and the template is loaded into the client.
Read Here is what you need to know about dynamic components in Angular for more details.
Dynamic template URLs in Angular 2
Although maybe not the most elegant solution, I used the DynamicComponentLoader and ElementRef to dynamically assign template value to a component. In fact, I was looking for a solution where I can add multiple custom components into a placeholder.
I tried service injection in the function as outlined by shmck this doesn't work as the services are not available yet when the template function is called. Indeed, this
refers to the Window object.
Reference URLs for the solution I used are to be found on: create dynamic anchorName/Components with ComponentResolver and ngFor in Angular2
I also refer this way to Plnkr1 and Plnkr2.
The site Dartdocs provides nice documentation on Angular 2 DynamicComponentLoader class, also applicable to TypeScript.
In short:
A simple Component as the to be used template
@Component({
selector: 'dt2-simple-block',
properties: ["idx"],
template: `<h1>Simple block for {{ idx }} </h1>`,
directives: []
})
class dt2SimpleBlock {
constructor() {
}
}
Constructor of the Component that holds all Components to be added (my app requires multiple childs to be included:
constructor(loader: DynamicComponentLoader, elementRef: ElementRef) {
//iterate
for (var i = 0; i < toSomething; i++) {
// build the template
var blockdirective = 'dt2-simple-block'
var template = '<' + blockdirective +
' idx="' + this.userBlocks.userHomePanelBlocks[i] +
'"></' + blockdirective + '>';
console.log(template); // debugging purpose
var directives = [dt2SimpleBlock];
loader.loadNextToLocation(toComponent(template, directives), elementRef);
}
And the helper function to be put somewhere as util
function toComponent(template, directives = []) {
@Component({ selector: 'fake-component' })
@View({ template, directives })
class FakeComponent { }
return FakeComponent;
}
Dynamic template in templatURL in angular2
And as you can see in this issue on the Angular repo, most probably we won't get that directive. There has been a long discussion whether we need this directive or not, and if not provided how we can implement it by our self.
I tried to make a simple example of how it can be implemented.
@Component({
selector: 'my-ng-include',
template: '<div #myNgIncludeContent></div>'
})
export class MyNgInclude implements OnInit {
@Input('src')
private templateUrl: string;
@ViewChild('myNgIncludeContent', { read: ViewContainerRef })
protected contentTarget: ViewContainerRef;
constructor(private componentResolver: ComponentResolver) {}
ngOnInit() {
var dynamicComponent = this.createContentComponent(this.templateUrl);
this.componentResolver.resolveComponent(dynamicComponent)
.then((factory: any) => this.contentTarget.createComponent(factory));
}
createContentComponent(templateUrl) {
@Component({
selector: 'my-ng-include-content',
templateUrl: templateUrl,
directives: FORM_DIRECTIVES,
})
class MyNgIncludeContent {}
return MyNgIncludeContent ;
}
}
For a demo check this Plunker.
Related Topics
How to Improve Performance of Ngrepeat Over a Huge Dataset (Angular.Js)
Event.Preventdefault() VS. Return False (No Jquery)
Javascript: Undefined !== Undefined
Create an Object from an Array of Keys and an Array of Values
How to Get the Browser Language Using JavaScript
Maintain Model of Scope When Changing Between Views in Angularjs
React - Changing an Uncontrolled Input
How to Split Comma Separated String Using JavaScript
The $.Param( ) Inverse Function in JavaScript/Jquery
How to Set Header and Options in Axios
How to Add/Remove a Class in JavaScript
Difference Between Date(Datestring) and New Date(Datestring)
The Definitive Best Way to Preload Images Using JavaScript/Jquery
How to Make a Shared State Between Two React Components
Chrome Extension - Get Dom Content