A simple plunker demonstrating Angular2 usage:
- Uses SystemJS + TypeScript to compile on the fly
- Includes binding, directives, http, pipes, and DI usage.
For opening
//our root app component | |
import {Component, NgModule} from '@angular/core' | |
import {BrowserModule} from '@angular/platform-browser' | |
import { RouterModule } from '@angular/router'; | |
import { HtmlOutlet } from './html-outlet'; | |
import { SharedModule } from './shared.module' | |
@Component({ | |
selector: 'my-app', | |
template: `<router-outlet></router-outlet>` | |
}) | |
export class AppComponent {} | |
@Component({ | |
selector: 'my-home', | |
template: ` | |
<h1>home</h1> | |
<html-outlet [html]="value"></html-outlet> | |
` | |
}) | |
export class HomeComponent { | |
value = `<span>Test interpolation {{5 + 6}}</span> | |
<div><a routerLink="/about">To about</a><my-test></my-test></div>`; | |
} | |
@Component({ | |
selector: 'my-about', | |
template: ` | |
<a routerLink="/">To home</a> | |
` | |
}) | |
export class AboutComponent {} | |
@NgModule({ | |
imports: [ | |
BrowserModule, | |
RouterModule.forRoot([ | |
{ path: '', component: HomeComponent }, | |
{ path: 'about', component: AboutComponent } | |
]), | |
SharedModule | |
], | |
exports: [HomeComponent, AboutComponent], | |
declarations: [ AppComponent, HtmlOutlet, HomeComponent, AboutComponent ], | |
bootstrap: [ AppComponent ] | |
}) | |
export class AppModule { } |
System.config({ | |
//use typescript for compilation | |
transpiler: 'typescript', | |
//typescript compiler options | |
typescriptOptions: { | |
emitDecoratorMetadata: true | |
}, | |
paths: { | |
'npm:': 'https://unpkg.com/' | |
}, | |
//map tells the System loader where to look for things | |
map: { | |
'app': './', | |
'@angular/core': 'npm:@angular/core/bundles/core.umd.js', | |
'@angular/common': 'npm:@angular/common/bundles/common.umd.js', | |
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', | |
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', | |
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', | |
'@angular/http': 'npm:@angular/http/bundles/http.umd.js', | |
'@angular/router': 'npm:@angular/router/bundles/router.umd.js', | |
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', | |
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js', | |
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js', | |
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js', | |
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js', | |
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', | |
'@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js', | |
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js', | |
'rxjs': 'npm:rxjs', | |
'typescript': 'npm:[email protected]/lib/typescript.js' | |
}, | |
//packages defines our app package | |
packages: { | |
app: { | |
main: './main.ts', | |
defaultExtension: 'ts' | |
}, | |
rxjs: { | |
defaultExtension: 'js' | |
} | |
} | |
}); |
import { | |
Component, | |
Directive, | |
NgModule, | |
Input, | |
ViewContainerRef, | |
Compiler, | |
ComponentFactory, | |
ModuleWithComponentFactories, | |
ComponentRef, | |
ReflectiveInjector | |
} from '@angular/core'; | |
import { RouterModule } from '@angular/router'; | |
import { CommonModule } from '@angular/common'; | |
import { SharedModule } from './shared.module'; | |
import { AppModule } from './app'; | |
export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> { | |
const cmpClass = class DynamicComponent {}; | |
const decoratedCmp = Component(metadata)(cmpClass); | |
@NgModule({ imports: [AppModule, CommonModule, RouterModule, SharedModule], declarations: [decoratedCmp] }) | |
class DynamicHtmlModule { } | |
return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule) | |
.then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => { | |
return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp); | |
}); | |
} | |
@Directive({ selector: 'html-outlet' }) | |
export class HtmlOutlet { | |
@Input() html: string; | |
cmpRef: ComponentRef<any>; | |
constructor(private vcRef: ViewContainerRef, private compiler: Compiler) { } | |
ngOnChanges() { | |
const html = this.html; | |
if (!html) return; | |
if(this.cmpRef) { | |
this.cmpRef.destroy(); | |
} | |
const compMetadata = new Component({ | |
selector: 'dynamic-html', | |
template: this.html, | |
}); | |
createComponentFactory(this.compiler, compMetadata) | |
.then(factory => { | |
const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector); | |
this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []); | |
}); | |
} | |
ngOnDestroy() { | |
if(this.cmpRef) { | |
this.cmpRef.destroy(); | |
} | |
} | |
} |
<!DOCTYPE html> | |
<html> | |
<head> | |
<base href="." /> | |
<title>angular2 playground</title> | |
<script>document.write('<base href="' + document.location + '" />');</script> | |
<script src="https://unpkg.com/zone.js/dist/zone.js"></script> | |
<script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script> | |
<script src="https://unpkg.com/[email protected]/Reflect.js"></script> | |
<script src="https://unpkg.com/[email protected]/dist/system.js"></script> | |
<script src="config.js"></script> | |
<script> | |
System.import('app') | |
.catch(console.error.bind(console)); | |
</script> | |
</head> | |
<body> | |
<my-app> | |
loading... | |
</my-app> | |
</body> | |
</html> |
//main entry point | |
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; | |
import {AppModule} from './app'; | |
platformBrowserDynamic().bootstrapModule(AppModule) |
http://stackoverflow.com/questions/40092639/how-to-render-a-dynamic-template-with-components-in-angular2/40522429#40522429