I am building a modal component in Angular 2 (and TypeScript) that will have different views/pages. It won't have tabs, but the concept is pretty similar. Basically I am struggling to find an approach to doing this.
Within my modal component, I want to output the different views/pages. Each one should be a component itself, because they don't have any markup in common. Plus, they will fetch data from service classes, so I need to be able to write specific logic for each view.
Basically what I want is something like:
// Within my modal component's template
<div *ngFor="#view of views">
// Render view component here
</div>
Where views
could be an array of the components, for instance. My first and main problem is that I am not sure how to output a collection of my views (components).
How can I output a collection of components within another component?
Also, I need a way to hide and show views, which is the only thing the views have in common. I was thinking of adding an isActive
variable to the views and showing/hiding them based on that. Would it be bad practice for the views components to either implement a ModalView
interface or extend from a base class to add this logic? From my modal component, I want to be able to control which view is displayed, so I need the views to have this logic in common.
I hope it is clear what I want to do. The solution may be simple, but right now I am a bit confused on how to go about it. A code example would be much appreciated!
You can create a "component factory" as a directive that loads appropriate components using DynamicComponentLoader, based on parameters you pass from your modal.
<component-factory *ngFor="#view of views"
(loaded)="addComponent($event)"
[name]="view.name"
[visible]="view.visible"></component-factory>
@Directive({ selector: 'component-factory' })
class ComponentFactory {
@Input() name;
@Input() visible;
@Output() loaded = new EventEmitter();
constructor(
private _dcl: DynamicComponentLoader,
private _eref: ElementRef) {
// import OneCmp, TwoCmp in this file...
private components: { one: OneCmp, two: TwoCmp }
ngOnInit() {
this._dcl.loadNextToLocation(
this.components[this.name],
this._eref)
// pass values to the loaded components
// and send it's instance to the parent
.then((ref: ComponentRef) => {
ref.instance.visible = this.visible;
this.loaded.emit(ref.instance)
});
}
}
Angular2 Dynamically Render Template
import { Component, View, DynamicComponentLoader, ElementRef} from 'angular2/core'; import {bootstrap} from 'angular2/platform/browser'
@Component({
selector: 'some-component',
properties: ['greeting'],
template: `
<b>{{ greeting }}</b>
`
})
class SomeComponent { }
@Component({
selector: 'app'
})
@View({
template: `
<h1>Before container</h1>
<div #container></div>
<h2>After container</h2>
`
})
class App {
loader: DynamicComponentLoader;
elementRef: ElementRef;
constructor(loader: DynamicComponentLoader, elementRef: ElementRef) {
this.laoder = loader;
this.elementRef = elementRef;
// Some async action (maybe ajax response with html in it)
setTimeout(() => this.renderTemplate(`
<div>
<h2>Hello</h2>
<some-component greeting="Oh, hey"></some-component>
</div>
full code : https://github.com/guyoung/GyPractice-Angular2Advanced/tree/master/apps/dynamically_render_template
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