├── src ├── assets │ └── .gitkeep ├── app │ ├── app.component.scss │ ├── app.component.html │ ├── app.component.ts │ ├── examples │ │ ├── template-examples.ts │ │ ├── runtime-compiler.module.ts │ │ └── template-examples.service.ts │ └── app.module.ts ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── styles.scss ├── tsconfig.app.json ├── main.ts ├── browserslist ├── index.html └── polyfills.ts ├── .vscode └── launch.json ├── .gitignore ├── tsconfig.json ├── package.json ├── README.md └── angular.json /src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | section { 2 | margin: 2em; 3 | } 4 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncrim/angular-dynamic-styleguide/HEAD/src/favicon.ico -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html, body { height: 100%; } 4 | body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } 5 | -------------------------------------------------------------------------------- /src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "main.ts", 9 | "polyfills.ts" 10 | ], 11 | "include": [ 12 | "**/*.d.ts" 13 | ], 14 | "exclude": [ 15 | "test.ts", 16 | "**/*.spec.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /src/browserslist: -------------------------------------------------------------------------------- 1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | # 5 | # For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed 6 | 7 | > 0.5% 8 | last 2 versions 9 | Firefox ESR 10 | not dead 11 | not IE 9-11 -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 |

Template Examples

3 |
4 | 5 |
6 |
{{example.id}}
7 |
8 | 10 |
11 | 12 |
{{example.template}}
13 |
14 |
15 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch Edge against localhost (ng)", 9 | "type": "pwa-msedge", 10 | "request": "launch", 11 | "url": "http://localhost:4200", 12 | "webRoot": "${workspaceFolder}", 13 | "showAsyncStacks": true 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Angular Dynamic Styleguide Example 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { TemplateExamplesService, TemplateExample } from './examples/template-examples.service'; 3 | 4 | @Component({ 5 | selector: 'app-root', 6 | templateUrl: 'app.component.html', 7 | styleUrls: ['app.component.scss'] 8 | }) 9 | export class AppComponent { 10 | 11 | constructor(private _examplesService: TemplateExamplesService) { } 12 | 13 | ngOnInit() { 14 | this._examplesService.getExamples().then((result) => this.examples = result); 15 | } 16 | 17 | public examples?: Map; 18 | } 19 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # profiling files 12 | chrome-profiler-events.json 13 | speed-measure-plugin.json 14 | 15 | # IDEs and editors 16 | /.idea 17 | .project 18 | .classpath 19 | .c9/ 20 | *.launch 21 | .settings/ 22 | *.sublime-workspace 23 | 24 | # IDE - VSCode 25 | .vscode/* 26 | !.vscode/settings.json 27 | !.vscode/tasks.json 28 | !.vscode/launch.json 29 | !.vscode/extensions.json 30 | 31 | # misc 32 | /.sass-cache 33 | /connect.lock 34 | /coverage 35 | /libpeerconnection.log 36 | npm-debug.log 37 | yarn-error.log 38 | testem.log 39 | /typings 40 | 41 | # System Files 42 | .DS_Store 43 | Thumbs.db 44 | -------------------------------------------------------------------------------- /src/app/examples/template-examples.ts: -------------------------------------------------------------------------------- 1 | import { Type, InjectionToken } from '@angular/core'; 2 | 3 | /** 4 | * Examples are defined by a template string, which is compiled at runtime. 5 | */ 6 | export interface UncompiledTemplateExamples { [id: string]: string }; 7 | 8 | /** Injection token for examples that are compiled by @see TemplateExamplesService. */ 9 | export const TEMPLATE_EXAMPLES = new InjectionToken('Template examples'); 10 | 11 | /** Define all the template examples that are compiled by @see TemplateExamplesService. */ 12 | export const templateExamples: UncompiledTemplateExamples = 13 | { 14 | 'icon': 15 | `add`, 16 | 17 | 'round-icon-button': 18 | ``, 19 | 20 | 'rectangle-button': 21 | ``, 22 | 23 | // 'ng-class': 24 | // `
Div with ngClass
` 25 | }; 26 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | 4 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 5 | import { MatToolbarModule } from '@angular/material/toolbar'; 6 | 7 | import { AppComponent } from './app.component'; 8 | import { TemplateExamplesService } from './examples/template-examples.service'; 9 | import { TEMPLATE_EXAMPLES, templateExamples } from './examples/template-examples'; 10 | import { RuntimeCompilerModule } from './examples/runtime-compiler.module'; 11 | 12 | @NgModule({ 13 | declarations: [ 14 | AppComponent 15 | ], 16 | imports: [ 17 | BrowserModule, 18 | BrowserAnimationsModule, 19 | MatToolbarModule, 20 | RuntimeCompilerModule 21 | ], 22 | providers: [ 23 | { provide: TEMPLATE_EXAMPLES, useValue: templateExamples }, 24 | TemplateExamplesService 25 | ], 26 | bootstrap: [AppComponent] 27 | }) 28 | export class AppModule { } 29 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "importHelpers": true, 9 | "skipLibCheck": true, // Helps build perf. Used by angular packages. 10 | "moduleResolution": "node", 11 | "downlevelIteration": true, 12 | "experimentalDecorators": true, 13 | // Strict options 14 | "strict": true, 15 | "noImplicitReturns": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "forceConsistentCasingInFileNames": true, 18 | "target": "es2016", // Can't use e2017 yet: https://github.com/angular/angular/issues/31730 19 | "module": "es2020", 20 | "types": [ 21 | "tslib" 22 | ], 23 | "lib": [ 24 | "dom", 25 | "es2020" 26 | ] 27 | }, 28 | "angularCompilerOptions": { 29 | "enableIvy": true, 30 | "strictTemplates": true, 31 | "strictInjectionParameters": true, 32 | "fullTemplateTypeCheck": true 33 | }, 34 | "exclude": [ 35 | "node_modules", 36 | "tmp" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-dynamic-styleguide", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "lint": "ng lint" 9 | }, 10 | "private": true, 11 | "dependencies": { 12 | "@angular/animations": "~12.2.3", 13 | "@angular/cdk": "~12.2.3", 14 | "@angular/common": "~12.2.3", 15 | "@angular/compiler": "~12.2.3", 16 | "@angular/core": "~12.2.3", 17 | "@angular/forms": "~12.2.3", 18 | "@angular/material": "^12.2.3", 19 | "@angular/platform-browser": "~12.2.3", 20 | "@angular/platform-browser-dynamic": "~12.2.3", 21 | "@angular/router": "~12.2.3", 22 | "core-js": "^3.16.1", 23 | "rxjs": "~7.3.0", 24 | "tslib": "^2.3.1", 25 | "zone.js": "~0.11.4" 26 | }, 27 | "devDependencies": { 28 | "@angular-devkit/build-angular": "~12.2.2", 29 | "@angular/cli": "~12.2.2", 30 | "@angular/compiler-cli": "~12.2.3", 31 | "@angular/language-service": "~12.2.3", 32 | "@types/node": "~16.6.1", 33 | "ts-node": "~10.2.0", 34 | "tslint": "~6.1.3", 35 | "typescript": "~4.3.5" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/app/examples/runtime-compiler.module.ts: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright 2018 Fintellect, Inc. All Rights Reserved. 3 | */ 4 | 5 | 6 | import { Compiler, COMPILER_OPTIONS, CompilerFactory, CompilerOptions, NgModule, ViewEncapsulation } from '@angular/core'; 7 | import { JitCompilerFactory } from '@angular/platform-browser-dynamic'; 8 | 9 | const compilerOptions: CompilerOptions = { 10 | useJit: true, 11 | defaultEncapsulation: ViewEncapsulation.None 12 | }; 13 | 14 | export function createCompiler(compilerFactory: CompilerFactory) { 15 | return compilerFactory.createCompiler([compilerOptions]); 16 | } 17 | 18 | /** 19 | * Include this module to use {@link Compiler} in production builds. 20 | * Unfortunately, even with this, we can't run style-guide using --configuration production, due to: 21 | * https://github.com/angular/angular/issues/27584 22 | */ 23 | @NgModule({ 24 | providers: [ 25 | { provide: COMPILER_OPTIONS, useValue: compilerOptions, multi: true }, 26 | { provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] }, 27 | { provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] } 28 | ] 29 | }) 30 | export class RuntimeCompilerModule { } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Dynamic Styleguide 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli). It has been updated to Angular version 12.x. 4 | 5 | It is a minimal example of an Angular StyleGuide containing examples that are compiled dynamically (at runtime). Dynamic compilation is used because it provides access to the Angular template source code, which is displayed in the styleguide. 6 | 7 | A key goal for this demo project was to get dynamically compiled components running with `ng build --prod` or `ng serve --prod`. Thanks to [this comment in github](https://github.com/angular/angular/issues/27584#issuecomment-446462051) I found that the key fix was to add `import 'core-js/es7/reflect';` to polyfills.ts. Even though it's not a real polyfill (it's needed on all browsers), it's required for dynamic compilation in --prod builds. 8 | 9 | Note that running dynamically compiled components with `ng build --prod` also requires 10 | 11 | ```json 12 | "buildOptimizer": false, 13 | ``` 14 | in the `production` configuration in `angular.json`. 15 | 16 | ## Development server 17 | 18 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 19 | 20 | ## Code scaffolding 21 | 22 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 23 | 24 | ## Build 25 | 26 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. 27 | 28 | ## Further help 29 | 30 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 31 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/weak-map'; 35 | // import 'core-js/es6/set'; 36 | 37 | /** 38 | * If the application will be indexed by Google Search, the following is required. 39 | * Googlebot uses a renderer based on Chrome 41. 40 | * https://developers.google.com/search/docs/guides/rendering 41 | **/ 42 | // import 'core-js/es6/array'; 43 | 44 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 45 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 46 | 47 | /** IE10 and IE11 requires the following for the Reflect API. */ 48 | // import 'core-js/es6/reflect'; 49 | 50 | /** 51 | * Web Animations `@angular/platform-browser/animations` 52 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 53 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 54 | **/ 55 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 56 | 57 | /** 58 | * By default, zone.js will patch all possible macroTask and DomEvents 59 | * user can disable parts of macroTask/DomEvents patch by setting following flags 60 | */ 61 | 62 | // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 63 | // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 64 | // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 65 | 66 | /* 67 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 68 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 69 | */ 70 | // (window as any).__Zone_enable_cross_context_check = true; 71 | 72 | /*************************************************************************************************** 73 | * Zone JS is required by default for Angular itself. 74 | */ 75 | import 'zone.js/dist/zone'; // Included with Angular CLI. 76 | 77 | 78 | /*************************************************************************************************** 79 | * APPLICATION IMPORTS 80 | */ 81 | // Needed to use dynamically compiled components in AOT/prod builds: https://github.com/angular/angular/issues/27584#issuecomment-446462051 82 | import 'core-js/proposals/reflect-metadata'; 83 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "angular-dynamic-styleguide": { 7 | "root": "", 8 | "sourceRoot": "src", 9 | "projectType": "application", 10 | "prefix": "app", 11 | "schematics": { 12 | "@schematics/angular:component": { 13 | "styleext": "scss" 14 | } 15 | }, 16 | "architect": { 17 | "build": { 18 | "builder": "@angular-devkit/build-angular:browser", 19 | "options": { 20 | "outputPath": "dist/angular-dynamic-styleguide", 21 | "index": "src/index.html", 22 | "main": "src/main.ts", 23 | "polyfills": "src/polyfills.ts", 24 | "tsConfig": "src/tsconfig.app.json", 25 | "assets": [ 26 | "src/favicon.ico", 27 | "src/assets" 28 | ], 29 | "styles": [ 30 | "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css", 31 | "src/styles.scss" 32 | ], 33 | "scripts": [], 34 | "sourceMap": { 35 | "styles": true, 36 | "scripts": true, 37 | "vendor": true 38 | }, 39 | "aot": true, 40 | "vendorChunk": true, 41 | "extractLicenses": false, 42 | // IMPORTANT: "buildOptimizer": false and "optimization": false is required for dynamic examples to work 43 | "buildOptimizer": false, 44 | "optimization": false, 45 | "namedChunks": true 46 | }, 47 | "configurations": { 48 | "production": { 49 | "fileReplacements": [ 50 | { 51 | "replace": "src/environments/environment.ts", 52 | "with": "src/environments/environment.prod.ts" 53 | } 54 | ], 55 | "outputHashing": "all", 56 | "sourceMap": false, 57 | "extractCss": true, 58 | "namedChunks": false, 59 | "aot": true, 60 | "extractLicenses": true, 61 | "vendorChunk": false, 62 | "buildOptimizer": false, 63 | "optimization": false, 64 | "budgets": [ 65 | { 66 | "type": "initial", 67 | "maximumWarning": "2mb", 68 | "maximumError": "5mb" 69 | } 70 | ] 71 | } 72 | } 73 | }, 74 | "serve": { 75 | "builder": "@angular-devkit/build-angular:dev-server", 76 | "options": { 77 | "browserTarget": "angular-dynamic-styleguide:build" 78 | }, 79 | "configurations": { 80 | "production": { 81 | "browserTarget": "angular-dynamic-styleguide:build:production" 82 | } 83 | } 84 | }, 85 | "extract-i18n": { 86 | "builder": "@angular-devkit/build-angular:extract-i18n", 87 | "options": { 88 | "browserTarget": "angular-dynamic-styleguide:build" 89 | } 90 | }, 91 | "lint": { 92 | "builder": "@angular-devkit/build-angular:tslint", 93 | "options": { 94 | "tsConfig": [ 95 | "src/tsconfig.app.json", 96 | "src/tsconfig.spec.json" 97 | ], 98 | "exclude": [ 99 | "**/node_modules/**" 100 | ] 101 | } 102 | } 103 | } 104 | } 105 | }, 106 | "defaultProject": "angular-dynamic-styleguide" 107 | } 108 | -------------------------------------------------------------------------------- /src/app/examples/template-examples.service.ts: -------------------------------------------------------------------------------- 1 | import { Compiler, Inject, Injectable, ModuleWithComponentFactories, NgModuleFactory, Type } from '@angular/core'; 2 | 3 | import { TEMPLATE_EXAMPLES, UncompiledTemplateExamples } from './template-examples'; 4 | import { Component, NgModule } from '@angular/core'; 5 | 6 | import { MatButtonModule } from '@angular/material/button'; 7 | import { MatIconModule } from '@angular/material/icon'; 8 | 9 | /** A component + template text from one of the @see exampleTemplates. */ 10 | export class TemplateExample { 11 | 12 | public set moduleFactory(f: NgModuleFactory) { 13 | this._moduleFactory = f; 14 | } 15 | public get moduleFactory(): NgModuleFactory { 16 | if (!this._moduleFactory) { 17 | throw new Error('NgModuleFactory should have been set'); 18 | } 19 | return this._moduleFactory; 20 | } 21 | private _moduleFactory?: NgModuleFactory; 22 | 23 | constructor(public readonly id: string, 24 | public readonly template: string, 25 | public readonly component: Type) { } 26 | } 27 | 28 | /** 29 | * Provides all the @see templateExamples compiled into a new module. This approach is necessary to provide 30 | * both template source code, as well as live components. 31 | * 32 | * @see templateExamples 33 | */ 34 | @Injectable({ 35 | providedIn: 'root' 36 | }) 37 | export class TemplateExamplesService { 38 | 39 | constructor(private _compiler: Compiler, 40 | @Inject(TEMPLATE_EXAMPLES) private _templateExamples: UncompiledTemplateExamples) { 41 | } 42 | 43 | private _compilePromise?: Promise; 44 | private _examples?: Map = undefined; 45 | private _compiledModule?: ModuleWithComponentFactories; 46 | 47 | /** 48 | * Creates and compiles example components. 49 | * 50 | * 2 sources describing how this is done: 51 | * https://github.com/apoterenko/ngx-dynamic-template/ 52 | * https://blog.angularindepth.com/here-is-what-you-need-to-know-about-dynamic-components-in-angular-ac1e96167f9e 53 | */ 54 | private async createAndCompileComponents(): Promise { 55 | const examples = new Map(); 56 | 57 | const components = Object.entries(this._templateExamples).map( 58 | ([id, value]) => { 59 | let template: string; 60 | let component: Type; 61 | template = value; 62 | // Create a new angular Component from each template 63 | component = Component({ template: template })(class { }); 64 | examples.set(id, new TemplateExample(id, template, component)); 65 | return component; 66 | } 67 | ); 68 | 69 | const examplesModule = NgModule({ 70 | declarations: [components], 71 | exports: [...components], 72 | entryComponents: [components], 73 | imports: [MatIconModule, MatButtonModule] 74 | })(class TemplateExamplesModule { 75 | }); 76 | 77 | this._compiledModule = await this._compiler.compileModuleAndAllComponentsAsync(examplesModule); 78 | 79 | // Store the ngModuleFactory in each example for easy access 80 | const moduleFactory = this._compiledModule?.ngModuleFactory; 81 | if (!!moduleFactory) { 82 | examples.forEach((example: TemplateExample, id: string) => { 83 | example.moduleFactory = moduleFactory; 84 | }); 85 | } 86 | 87 | this._examples = examples; 88 | } 89 | 90 | public async getExample(id: string): Promise { 91 | if (!this._compilePromise) { 92 | this._compilePromise = this.createAndCompileComponents(); 93 | } 94 | 95 | await this._compilePromise; 96 | 97 | return this._examples && this._examples.get(id); 98 | } 99 | 100 | 101 | public async getExamples(): Promise | undefined> { 102 | if (!this._compilePromise) { 103 | this._compilePromise = this.createAndCompileComponents(); 104 | } 105 | 106 | await this._compilePromise; 107 | return this._examples; 108 | } 109 | 110 | } 111 | --------------------------------------------------------------------------------