File tree Expand file tree Collapse file tree 23 files changed +10672
-0
lines changed Open diff view settings
demos/embedded-config-angular7 Expand file tree Collapse file tree 23 files changed +10672
-0
lines changed Open diff view settings
Original file line number Diff line number Diff line change 1010
1111## My JavaScript Demos - I Love JavaScript!
1212
13+ * [ Using Embedded Data To Provide Request-Specific Application Configuration In Angular 7.2.0] ( https://bennadel.github.io/JavaScript-Demos/demos/embedded-config-angular7/ )
1314* [ Animating Elements In From A Mouse-Event Location In Vue.js 2.5.21] ( https://bennadel.github.io/JavaScript-Demos/demos/animate-enter-position-vue2/ )
1415* [ Creating A Pandora Radio Station List Animation In Vue.js 2.5.21] ( https://bennadel.github.io/JavaScript-Demos/demos/pandora-list-vue2/ )
1516* [ Creating A Bind-Once Structural Directive In Angular 7.1.4] ( https://bennadel.github.io/JavaScript-Demos/demos/bind-once-angular7/ )
Original file line number Diff line number Diff line change 1+
2+ # Now that we're using Webpack, we can install modules locally and just ignore
3+ # them since the assets are baked into the compiled modules.
4+ node_modules /
Original file line number Diff line number Diff line change 1+ component
2+ output = false
3+ hint = " I define the application settings and event handlers."
4+ {
5+
6+ this .name = hash ( getCurrentTemplatePath () );
7+ this .applicationTimeout = createTimeSpan ( 0 , 0 , 10 , 0 );
8+ this .sessionManagement = false ;
9+
10+ // This ColdFusion application framework file is used for the CFML version
11+ // of the embedded-configuration demo.
12+
13+ }
Original file line number Diff line number Diff line change 1+
2+ :host {
3+ display : block ;
4+ font-size : 18px ;
5+ }
Original file line number Diff line number Diff line change 1+
2+ // Import the core angular services.
3+ import { Component } from "@angular/core" ;
4+
5+ // Import the application components and services.
6+ import { AppConfig } from "./app.config" ;
7+ import { Company } from "./app.config" ;
8+
9+ // ----------------------------------------------------------------------------------- //
10+ // ----------------------------------------------------------------------------------- //
11+
12+ @Component ( {
13+ selector : "my-app" ,
14+ styleUrls : [ "./app.component.less" ] ,
15+ template :
16+ `
17+ <h2>
18+ Dynamic Company Configuration
19+ </h2>
20+
21+ <ul>
22+ <li>
23+ <strong>ID:</strong> {{ company.id }}
24+ </li>
25+ <li>
26+ <strong>Name:</strong> {{ company.name }}
27+ </li>
28+ <li>
29+ <strong>Establised:</strong> {{ company.established }}
30+ </li>
31+ </ul>
32+ `
33+ } )
34+ export class AppComponent {
35+
36+ public company : Company ;
37+
38+ // I initialize the app component.
39+ constructor ( config : AppConfig ) {
40+
41+ console . group ( "App Component Constructor" ) ;
42+ console . log ( "App Config" ) ;
43+ console . log ( config ) ;
44+ console . groupEnd ( ) ;
45+
46+ this . company = config . company ;
47+
48+ }
49+
50+ }
Original file line number Diff line number Diff line change 1+
2+ export interface Company {
3+ id : number ;
4+ name : string ;
5+ established : number ;
6+ }
7+
8+ // NOTE: Using name "AppConfig" for "Declaration Merging".
9+ export interface AppConfig {
10+ company : Company ;
11+ version : string ;
12+ }
13+
14+ // NOTE: Using name "AppConfig" for "Declaration Merging".
15+ export abstract class AppConfig {
16+ // By creating an Abstract Class that has the same name as an Interface, we get to
17+ // leverage "Declaration Merging" in TypeScript. This tells TypeScript to assume
18+ // that this "AppConfig" class will implement the "AppConfig" interface without
19+ // having to actually implement the interface in the class definition. This gives us
20+ // some wiggle-room to use a dynamic, runtime implementation while still getting the
21+ // benefits of type-safety.
22+ // --
23+ // AND, we get to use the Abstract Class as a dependency-injection token since it
24+ // represents a "Type" within our application.
25+ }
Original file line number Diff line number Diff line change 1+
2+ // Import the core angular services.
3+ import { BrowserModule } from "@angular/platform-browser" ;
4+ import { NgModule } from "@angular/core" ;
5+
6+ // Import the application components and services.
7+ import { AppComponent } from "./app.component" ;
8+ import { AppConfig } from "./app.config" ;
9+
10+ // ----------------------------------------------------------------------------------- //
11+ // ----------------------------------------------------------------------------------- //
12+
13+ // The contextual page request has embedded configuration data into the JavaScript
14+ // execution context using the window.appConfig key. Since we don't want to couple the
15+ // rest of our Angular application to this implementation detail, we're going to map
16+ // this config object onto an injectable Type that also provides us with type-safety.
17+ export function getAppConfig ( ) : AppConfig {
18+
19+ var config : AppConfig = ( < any > window ) . appConfig ;
20+
21+ // Assert that the page request provided the configuration.
22+ if ( ! config ) {
23+
24+ throw ( new Error ( "Application bootstrapping could not locate 'window.appConfig' value." ) ) ;
25+
26+ }
27+
28+ return ( config ) ;
29+
30+ }
31+
32+ // ----------------------------------------------------------------------------------- //
33+ // ----------------------------------------------------------------------------------- //
34+
35+ @NgModule ( {
36+ imports : [
37+ BrowserModule
38+ ] ,
39+ declarations : [
40+ AppComponent
41+ ] ,
42+ providers : [
43+ // Provide the AppConfig as an injectable Type for the rest of the application
44+ // components and services.
45+ {
46+ provide : AppConfig ,
47+ useFactory : getAppConfig
48+ }
49+ ] ,
50+ bootstrap : [
51+ AppComponent
52+ ]
53+ } )
54+ export class AppModule {
55+ // ...
56+ }
Original file line number Diff line number Diff line change 1+ <cfscript >
2+
3+ // Simulate request-specific, dynamic configuration using random values.
4+ switch ( randRange ( 1 , 3 ) ) {
5+ case " 1" :
6+
7+ company = {
8+ " id" : 1 ,
9+ " name" : " Acme Corp" ,
10+ " established" : 1908
11+ };
12+
13+ break ;
14+ case " 2" :
15+
16+ company = {
17+ " id" : 2 ,
18+ " name" : " Evil Corp" ,
19+ " established" : 2007
20+ };
21+
22+ break ;
23+ case " 3" :
24+
25+ company = {
26+ " id" : 3 ,
27+ " name" : " Happy Corp" ,
28+ " established" : 1980
29+ };
30+
31+ break ;
32+ }
33+
34+ config = {
35+ " company" : company ,
36+ " version" : " 2019.01.11.6.19.0"
37+ };
38+
39+ </cfscript >
40+
41+ <!--- ------------------------------------------------------------------------------ --->
42+ <!--- ------------------------------------------------------------------------------ --->
43+
44+ <!--- Reset the output buffer. --->
45+ <cfcontent type =" text/html; charset=utf-8" />
46+
47+ <!doctype html>
48+ <html lang =" en" >
49+ <head >
50+ <meta charset =" utf-8" />
51+
52+ <title >
53+ Using Embedded Data To Provide Request-Specific Application Configuration In Angular 7.2.0 (CFML Version)
54+ </title >
55+
56+ <cfoutput >
57+ <script type =" text/javascript" >
58+
59+ // Since the Angular application needs to be configured on a per-request
60+ // basis, we can provide the ColdFusion data in the JavaScript context by
61+ // serializing the data on the ColdFusion server and then parsing it on the
62+ // client as JSON.
63+ // --
64+ // NOTE: By using the encodeForJavaScript() function, we are preventing the
65+ // injection of Cross-Site Scripting (XSS) attacks in any user-provided
66+ // content that may exist within the configuration payload (ex, company.name).
67+ window .appConfig = JSON .parse ( " #encodeForJavaScript( serializeJson( config ) )#" );
68+
69+ </script >
70+ </cfoutput >
71+ </head >
72+ <body >
73+
74+ <h1 >
75+ Using Embedded Data To Provide Request-Specific Application Configuration In Angular 7.2.0 (CFML Version)
76+ </h1 >
77+
78+ <my -app ></my -app >
79+
80+ </body >
81+ </html >
Original file line number Diff line number Diff line change 1+ <!doctype html>
2+ < html lang ="en ">
3+ < head >
4+ < meta charset ="utf-8 " />
5+
6+ < title >
7+ Using Embedded Data To Provide Request-Specific Application Configuration In Angular 7.2.0
8+ </ title >
9+
10+ < script type ="text/javascript ">
11+
12+ // Simulate request-specific, dynamic configuration using random values.
13+ switch ( ( Math . floor ( Math . random ( ) * 10 ) % 3 ) + 1 ) {
14+ case 1 :
15+
16+ var company = {
17+ "id" : 1 ,
18+ "name" : "Acme Corp" ,
19+ "established" : 1908
20+ } ;
21+
22+ break ;
23+ case 2 :
24+
25+ var company = {
26+ "id" : 2 ,
27+ "name" : "Evil Corp" ,
28+ "established" : 2007
29+ } ;
30+
31+ break ;
32+ case 3 :
33+
34+ var company = {
35+ "id" : 3 ,
36+ "name" : "Happy Corp" ,
37+ "established" : 1980
38+ } ;
39+
40+ break ;
41+ }
42+
43+ // Provide external configuration data on a global key so that it can be consumed
44+ // by the Angular application bootstrapping process.
45+ window . appConfig = {
46+ "company" : company ,
47+ "version" : "2019.01.11.6.19.0"
48+ } ;
49+
50+ </ script >
51+ </ head >
52+ < body >
53+
54+ < h1 >
55+ Using Embedded Data To Provide Request-Specific Application Configuration In Angular 7.2.0
56+ </ h1 >
57+
58+ < my-app >
59+ < p >
60+ < em > Loading files...</ em >
61+ </ p >
62+
63+ < p >
64+ npm Run Scripts:
65+ </ p >
66+
67+ < ul >
68+ < li >
69+ < strong > npm run build</ strong > — Compiles the .ts file into bundles.
70+ </ li >
71+ < li >
72+ < strong > npm run watch</ strong > — Compiles the .ts file into bundles and then watches files for changes.
73+ </ li >
74+ </ ul >
75+ </ my-app >
76+
77+ </ body >
78+ </ html >
Original file line number Diff line number Diff line change 1+
2+ // Import these libraries for their side-effects.
3+ import "core-js/client/shim.min.js" ;
4+ import "zone.js/dist/zone.js" ;
You can’t perform that action at this time.
0 commit comments