LP#1775466 Dynamic module as angular element experiment
authorBill Erickson <berickxx@gmail.com>
Thu, 14 Jun 2018 17:31:14 +0000 (13:31 -0400)
committerBill Erickson <berickxx@gmail.com>
Thu, 14 Jun 2018 17:31:14 +0000 (13:31 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
13 files changed:
Open-ILS/src/eg2/README.adoc
Open-ILS/src/eg2/angular.json
Open-ILS/src/eg2/package.json
Open-ILS/src/eg2/src/app/common.module.ts
Open-ILS/src/eg2/src/app/dynamic.module.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/util/dynamic.component.ts
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.module.ts
Open-ILS/src/eg2/src/dynamic.html [new file with mode: 0644]
Open-ILS/src/eg2/src/dynamic.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/index.html
Open-ILS/src/eg2/src/polyfills.ts

index 8bd92c2..8ff6c4f 100644 (file)
@@ -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
index d3cc725..3218f85 100644 (file)
@@ -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",
         }
       }
     },
+    "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": "",
index cb745d2..703ed6e 100644 (file)
@@ -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",
index 89fef35..ccb47fa 100644 (file)
@@ -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 (file)
index 0000000..928ff89
--- /dev/null
@@ -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() {}
+}
+
index 2f67671..a5c058a 100644 (file)
@@ -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: '<ng-container #container></ng-container>'
+  template: '<ng-container #container></ng-container>',
+  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<boolean>;
@@ -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<boolean>();
     }
 
     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<void> {
+        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();
     }
 
 }
index fda77a4..cd47926 100644 (file)
 <eg-dynamic-component #dynamic></eg-dynamic-component>
 
 <br/>
+-->
 
+<!--
 <b>Dynamic Complent via URL Inline</b>
 <eg-dynamic-component 
-  contentUrl="/test-template.html
-  [contextData]="{world:'world'}"
+  [content-url-string]="'/test-template.html'
+  context-data="{world:'world'}"
   (onComplete)="renderLocal=!$event">
 </eg-dynamic-component>
 <div *ngIf="renderLocal">
   <b>fall through local template: hello {{world}}</b>
 </div>
--->
 
 <br/><br/>
 
+<eg-dynamic-component 
+  content="<b>Hello All</b>"
+  [context-data]="{world:'world'}"
+  (onComplete)="renderLocal=!$event">
+</eg-dynamic-component>
+-->
+
+
 <!-- grid stuff -->
 <ng-template #cellTmpl let-row="row" let-col="col" let-userContext="userContext">
   HELLO {{userContext.hello}}
index 1dc600f..357a94b 100644 (file)
@@ -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<any>;
 
-    //@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() {
index 00c7cb7..96e7714 100644 (file)
@@ -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 (file)
index 0000000..3d59d56
--- /dev/null
@@ -0,0 +1,9 @@
+<!doctype html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <base href="/eg2">
+</head>
+<body>
+</body>
+</html>
diff --git a/Open-ILS/src/eg2/src/dynamic.ts b/Open-ILS/src/eg2/src/dynamic.ts
new file mode 100644 (file)
index 0000000..baabb53
--- /dev/null
@@ -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));
index 43bb6ac..eb5a20d 100644 (file)
@@ -3,7 +3,7 @@
 <head>
   <meta charset="utf-8">
   <title i18n="Page Title">AngEG</title>
-  <base href="/webby">
+  <base href="/eg2">
 
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <link rel="icon" type="image/x-icon" href="favicon.ico">
   <script src="/js/dojo/opensrf/JSON_v1.js"></script>
   <script src="/js/dojo/opensrf/opensrf.js"></script>
   <script src="/js/dojo/opensrf/opensrf_ws.js"></script>
+  <!-- import the dynamic Angular Element component -->
+  <script type="text/javascript" src="/eg2/dynamic/runtime.js"></script>
+
+  <!-- probably don't need styles ... -->
+
+<script>
+  // https://github.com/stackblitz/core/issues/475
+       (function () {
+       'use strict';
+
+       (()=>{if(!window.customElements)return;const a=window.HTMLElement,b=window.customElements.define,c=window.customElements.get,d=new Map,e=new Map;let f=!1,g=!1;window.HTMLElement=function(){if(!f){const a=d.get(this.constructor),b=c.call(window.customElements,a);g=!0;const e=new b;return e}f=!1;}, window.HTMLElement.prototype=a.prototype;Object.defineProperty(window,'customElements',{value:window.customElements,configurable:!0,writable:!0}), Object.defineProperty(window.customElements,'define',{value:(c,h)=>{const i=h.prototype,j=class extends a{constructor(){super(), Object.setPrototypeOf(this,i), g||(f=!0, h.call(this)), g=!1;}},k=j.prototype;j.observedAttributes=h.observedAttributes, k.connectedCallback=i.connectedCallback, k.disconnectedCallback=i.disconnectedCallback, k.attributeChangedCallback=i.attributeChangedCallback, k.adoptedCallback=i.adoptedCallback, d.set(h,c), e.set(c,h), b.call(window.customElements,c,j);},configurable:!0,writable:!0}), Object.defineProperty(window.customElements,'get',{value:a=>e.get(a),configurable:!0,writable:!0});})();
+       /**
+       @license
+       Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
+       This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+       The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+       The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+       Code distributed by Google as part of the polymer project is also
+       subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+       */
+       }());
+</script>
+
+  <script type="text/javascript" src="/eg2/dynamic/polyfills.js"></script>
+  <script type="text/javascript" src="/eg2/dynamic/styles.js"></script>
+  <script type="text/javascript" src="/eg2/dynamic/vendor.js"></script>
+  <script type="text/javascript" src="/eg2/dynamic/main.js"></script>
+  <!-- END import the dynamic Angular Element component -->
+
 </body>
 </html>
index e073082..a7822cd 100644 (file)
@@ -64,7 +64,6 @@ import 'core-js/es7/reflect';
 import 'zone.js/dist/zone';  // Included with Angular CLI.
 
 
-
 /***************************************************************************************************
  * APPLICATION IMPORTS
  */