From e505983e0bf1c1aab04080a46d217a69567dbc13 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Thu, 14 Jun 2018 13:31:14 -0400 Subject: [PATCH] LP#1775466 Dynamic module as angular element experiment Signed-off-by: Bill Erickson --- Open-ILS/src/eg2/README.adoc | 2 +- Open-ILS/src/eg2/angular.json | 93 +++++++++++++++++++++- Open-ILS/src/eg2/package.json | 1 + Open-ILS/src/eg2/src/app/common.module.ts | 10 +-- Open-ILS/src/eg2/src/app/dynamic.module.ts | 23 ++++++ .../eg2/src/app/share/util/dynamic.component.ts | 22 +++-- .../src/app/staff/sandbox/sandbox.component.html | 15 +++- .../eg2/src/app/staff/sandbox/sandbox.component.ts | 9 ++- .../eg2/src/app/staff/sandbox/sandbox.module.ts | 3 +- Open-ILS/src/eg2/src/dynamic.html | 9 +++ Open-ILS/src/eg2/src/dynamic.ts | 12 +++ Open-ILS/src/eg2/src/index.html | 31 +++++++- Open-ILS/src/eg2/src/polyfills.ts | 1 - 13 files changed, 204 insertions(+), 27 deletions(-) create mode 100644 Open-ILS/src/eg2/src/app/dynamic.module.ts create mode 100644 Open-ILS/src/eg2/src/dynamic.html create mode 100644 Open-ILS/src/eg2/src/dynamic.ts diff --git a/Open-ILS/src/eg2/README.adoc b/Open-ILS/src/eg2/README.adoc index 8bd92c22b9..8ff6c4f015 100644 --- a/Open-ILS/src/eg2/README.adoc +++ b/Open-ILS/src/eg2/README.adoc @@ -73,7 +73,7 @@ $ ng build --deploy-url /eg2/ --base-href /eg2/ --output-path ../../web/eg2/ [source,sh] --------------------------------------------------------------------- -$ ng build --aot --prod --deploy-url /eg2/ --base-href /eg2/ --output-path ../../web/eg2/ +$ ng build --aot --prod --deploy-url /eg2/ --------------------------------------------------------------------- === Testing diff --git a/Open-ILS/src/eg2/angular.json b/Open-ILS/src/eg2/angular.json index d3cc725f1d..3218f852a2 100644 --- a/Open-ILS/src/eg2/angular.json +++ b/Open-ILS/src/eg2/angular.json @@ -11,7 +11,7 @@ "build": { "builder": "@angular-devkit/build-angular:browser", "options": { - "outputPath": "dist", + "outputPath": "../../web/eg2/", "index": "src/index.html", "main": "src/main.ts", "tsConfig": "src/tsconfig.app.json", @@ -93,6 +93,97 @@ } } }, + "eg-dynamic": { + "root": "", + "sourceRoot": "src", + "projectType": "application", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "../../web/eg2/dynamic", + "index": "src/dynamic.html", + "main": "src/dynamic.ts", + "tsConfig": "src/tsconfig.app.json", + "polyfills": "src/polyfills.ts", + "assets": [ + "src/assets", + "src/favicon.ico" + ], + "styles": [ + "src/styles.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "extractCss": true, + "namedChunks": false, + "aot": false, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ] + } + } + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "eg:build" + }, + "configurations": { + "production": { + "browserTarget": "eg:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "eg:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "src/test.ts", + "karmaConfig": "./karma.conf.js", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.spec.json", + "scripts": [], + "styles": [ + "src/styles.css" + ], + "assets": [ + "src/assets", + "src/favicon.ico" + ] + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "src/tsconfig.app.json", + "src/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "eg-e2e": { "root": "", "sourceRoot": "", diff --git a/Open-ILS/src/eg2/package.json b/Open-ILS/src/eg2/package.json index cb745d20af..703ed6e758 100644 --- a/Open-ILS/src/eg2/package.json +++ b/Open-ILS/src/eg2/package.json @@ -17,6 +17,7 @@ "@angular/common": "6.0.1", "@angular/compiler": "6.0.1", "@angular/core": "6.0.1", + "@angular/elements": "^6.0.5", "@angular/forms": "6.0.1", "@angular/http": "6.0.1", "@angular/platform-browser": "6.0.1", diff --git a/Open-ILS/src/eg2/src/app/common.module.ts b/Open-ILS/src/eg2/src/app/common.module.ts index 89fef3573d..ccb47fa515 100644 --- a/Open-ILS/src/eg2/src/app/common.module.ts +++ b/Open-ILS/src/eg2/src/app/common.module.ts @@ -27,18 +27,13 @@ import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component'; import {PromptDialogComponent} from '@eg/share/dialog/prompt.component'; import {ProgressDialogComponent} from '@eg/share/dialog/progress.component'; -// DynamicComponent only works in JIT compilation mode. -// Leaving for now as reference while considering alternatives -import {DynamicComponent} from '@eg/share/util/dynamic.component'; - @NgModule({ declarations: [ PrintComponent, DialogComponent, ConfirmDialogComponent, PromptDialogComponent, - ProgressDialogComponent, - DynamicComponent + ProgressDialogComponent ], imports: [ CommonModule, @@ -57,8 +52,7 @@ import {DynamicComponent} from '@eg/share/util/dynamic.component'; DialogComponent, ConfirmDialogComponent, PromptDialogComponent, - ProgressDialogComponent, - DynamicComponent + ProgressDialogComponent ] }) diff --git a/Open-ILS/src/eg2/src/app/dynamic.module.ts b/Open-ILS/src/eg2/src/app/dynamic.module.ts new file mode 100644 index 0000000000..928ff89dad --- /dev/null +++ b/Open-ILS/src/eg2/src/app/dynamic.module.ts @@ -0,0 +1,23 @@ +/** + */ +import {BrowserModule} from '@angular/platform-browser'; +import {NgModule, Injector, Compiler} from '@angular/core'; +import {createCustomElement} from '@angular/elements'; +import {HttpClientModule} from '@angular/common/http'; +import {DynamicComponent} from '@eg/share/util/dynamic.component'; + +@NgModule({ + declarations: [DynamicComponent], + imports: [BrowserModule, HttpClientModule], + entryComponents: [DynamicComponent] +}) + +export class DynamicModule { + constructor(private injector: Injector) { + const dynComp = createCustomElement(DynamicComponent, {injector}); + customElements.define('eg-dynamic-component', dynComp); + } + + ngDoBootstrap() {} +} + diff --git a/Open-ILS/src/eg2/src/app/share/util/dynamic.component.ts b/Open-ILS/src/eg2/src/app/share/util/dynamic.component.ts index 2f67671ee5..a5c058ad87 100644 --- a/Open-ILS/src/eg2/src/app/share/util/dynamic.component.ts +++ b/Open-ILS/src/eg2/src/app/share/util/dynamic.component.ts @@ -2,7 +2,8 @@ * WARNING: This component only works when using the JIT compiler. * Compiling --aot prevents the JitCompiler from working. */ -import {Component, OnInit, ViewChild, Input, Output, TemplateRef} from '@angular/core'; +import {Component, OnInit, ViewChild, Input} from '@angular/core'; +import {Output, TemplateRef, ViewEncapsulation} from '@angular/core'; import {Compiler, ViewContainerRef, NgModule, EventEmitter} from '@angular/core'; import {HttpClient} from '@angular/common/http'; @@ -16,7 +17,8 @@ import {HttpClient} from '@angular/common/http'; @Component({ selector: 'eg-dynamic-component', - template: '' + template: '', + encapsulation: ViewEncapsulation.Native }) export class DynamicComponent implements OnInit { @@ -24,9 +26,9 @@ export class DynamicComponent implements OnInit { @ViewChild('container', {read: ViewContainerRef}) private container: ViewContainerRef; - @Input() content: string; - @Input() contentUrl: string; - @Input() contextData: any; + @Input() public content: string; + @Input() public contentUrl: string; + @Input() public contextData: any; // Emits true if the content was render-able, false otherwise @Output() onComplete: EventEmitter; @@ -35,11 +37,14 @@ export class DynamicComponent implements OnInit { private compiler: Compiler, private http: HttpClient ) { - console.warn("DynamicComponent only works in JIT compilation mode"); + //console.warn("DynamicComponent only works in JIT compilation mode"); this.onComplete = new EventEmitter(); } ngOnInit() { + console.log(`init'ing DynamicComponent with url `, this.contentUrl); + console.log(`init'ing DynamicComponent with html`, this.content); + console.log(`init'ing DynamicComponent with data`, this.contextData); if (this.contentUrl) { this.buildFromUrl(this.contentUrl, this.contextData); } else if (this.content) { @@ -62,6 +67,8 @@ export class DynamicComponent implements OnInit { // Returns a promise which resolves if the requested URL // was found and was render-able, rejected otherwise. buildFromUrl(url: string, context: any = {}): Promise { + console.log(`Building dynamic component from ${url}`); + console.log(`Building dynamic component with context`, context); return this.http.get(url, {responseType: 'text'}).toPromise() .then( html => { @@ -98,11 +105,12 @@ export class DynamicComponent implements OnInit { ); const component = this.container.createComponent(factory); + console.log('assigning context to component: ', context); Object.assign(component.instance, context); // If context changes at a later stage, the change detection // may need to be triggered manually: - // component.changeDetectorRef.detectChanges(); + component.changeDetectorRef.detectChanges(); } } diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html index fda77a4d0b..cd479268bf 100644 --- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html +++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html @@ -84,20 +84,29 @@
+--> +

+ + +--> + + HELLO {{userContext.hello}} diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts index 1dc600ff3e..357a94b352 100644 --- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts @@ -12,7 +12,6 @@ import {PcrudService} from '@eg/core/pcrud.service'; import {Pager} from '@eg/share/util/pager'; import {DateSelectComponent} from '@eg/share/date-select/date-select.component'; import {PrintService} from '@eg/share/print/print.service'; -//import {DynamicComponent} from '@eg/share/util/dynamic.component'; @Component({ templateUrl: 'sandbox.component.html' @@ -28,9 +27,6 @@ export class SandboxComponent implements OnInit { @ViewChild('printTemplate') private printTemplate: TemplateRef; - //@ViewChild('dynamic') private dynamic: DynamicComponent; - //@ViewChild('dynamicUrl') private dynamicUrl: DynamicComponent; - // @ViewChild('helloStr') private helloStr: StringComponent; gridDataSource: GridDataSource = new GridDataSource(); @@ -82,6 +78,11 @@ export class SandboxComponent implements OnInit { this.dynamicUrl.buildFromUrl( '/test-template.html', {world: this.world}); */ + + const dyn: any = document.createElement('eg-dynamic-component'); + dyn.contentUrl = '/test-template.html'; + dyn.contextData = {world: this.world}; + document.body.appendChild(dyn); } doPrint() { diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.module.ts b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.module.ts index 00c7cb7516..96e7714720 100644 --- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.module.ts @@ -1,10 +1,11 @@ -import {NgModule} from '@angular/core'; +import {NgModule, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; import {StaffCommonModule} from '@eg/staff/common.module'; import {SandboxRoutingModule} from './routing.module'; import {SandboxComponent} from './sandbox.component'; import {GridModule} from '@eg/share/grid/grid.module'; @NgModule({ + schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: [ SandboxComponent ], diff --git a/Open-ILS/src/eg2/src/dynamic.html b/Open-ILS/src/eg2/src/dynamic.html new file mode 100644 index 0000000000..3d59d56ee4 --- /dev/null +++ b/Open-ILS/src/eg2/src/dynamic.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Open-ILS/src/eg2/src/dynamic.ts b/Open-ILS/src/eg2/src/dynamic.ts new file mode 100644 index 0000000000..baabb53e65 --- /dev/null +++ b/Open-ILS/src/eg2/src/dynamic.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { DynamicModule } from './app/dynamic.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(DynamicModule) + .catch(err => console.log(err)); diff --git a/Open-ILS/src/eg2/src/index.html b/Open-ILS/src/eg2/src/index.html index 43bb6ac79a..eb5a20d60b 100644 --- a/Open-ILS/src/eg2/src/index.html +++ b/Open-ILS/src/eg2/src/index.html @@ -3,7 +3,7 @@ AngEG - + @@ -27,5 +27,34 @@ + + + + + + + + + + + + + diff --git a/Open-ILS/src/eg2/src/polyfills.ts b/Open-ILS/src/eg2/src/polyfills.ts index e073082c1c..a7822cde5f 100644 --- a/Open-ILS/src/eg2/src/polyfills.ts +++ b/Open-ILS/src/eg2/src/polyfills.ts @@ -64,7 +64,6 @@ import 'core-js/es7/reflect'; import 'zone.js/dist/zone'; // Included with Angular CLI. - /*************************************************************************************************** * APPLICATION IMPORTS */ -- 2.11.0