{"id":2346,"date":"2020-02-20T15:15:16","date_gmt":"2020-02-20T15:15:16","guid":{"rendered":"http:\/\/salientsoft.co.uk\/?p=2346"},"modified":"2020-02-20T16:05:41","modified_gmt":"2020-02-20T16:05:41","slug":"using-the-angular-app_initializer","status":"publish","type":"post","link":"https:\/\/salientsoft.co.uk\/?p=2346","title":{"rendered":"Using the Angular APP_INITIALIZER"},"content":{"rendered":"<p>This allows the use of asynchronous operations (such as configuration loading) at Angular bootstrap time. It is documented (somewhat minimally to say the least) <strong><a href=\"https:\/\/angular.io\/api\/core\/APP_INITIALIZER\">here<\/a>.<\/strong><\/p>\n<p>In my case I needed it to allow early script loading of (in my case Yoti) external scripts at bootstrap time. A Yoti script overwrote some promise code that had already been patched by zone.js earlier. Subsequently, zone.js detected this and the application failed. This is documented <strong><a href=\"https:\/\/salientsoft.co.uk\/?p=2339\">here<\/a><\/strong>. I also used it to load the app configuration dynamically, rather than from index.html. As well as being a better design due to decoupling from index.html and opening the door to pulling the configuration from an external provider, this also allowed multiple configuration sets to be selectable e.g. from a query string parameter in the url.<\/p>\n<p><strong><a href=\"https:\/\/stackoverflow.com\/questions\/49707830\/angular-how-to-correctly-implement-app-initializer\">This Stack Overflow post<\/a><\/strong> shows how to implement the APP_INITIALIZER.\u00a0\u00a0<strong><a href=\"https:\/\/www.tektutorialshub.com\/angular\/angular-how-to-use-app-initializer\/\">This tutorial post<\/a><\/strong> does the same, and goes into details about using multiple providers via a multi provider token. Basically you need to pass a function or a lambda which returns a promise, which completes when your asynchronous operation is done. One point worthy of note is that when rejecting a promise, you need to pass something in the reject, or Angular throws an error stating\u00a0<em>Cannot read property &#8216;ngOriginalError&#8217; of undefined<\/em>.<\/p>\n<p>My implementation is here:<\/p>\n<blockquote><p>@NgModule({<br \/>\ndeclarations: [<br \/>\nAppComponent,<br \/>\nFabricComponent<br \/>\n],<br \/>\nimports: [<br \/>\nBrowserModule,<br \/>\nBrowserAnimationsModule,<br \/>\n&#8230;<br \/>\n],<br \/>\nschemas: [CUSTOM_ELEMENTS_SCHEMA],<br \/>\nproviders: [<br \/>\n&#8230;,<br \/>\nConfigurationService,<br \/>\nConfigurationValidator,<br \/>\nScriptLoader,<br \/>\nPreBootScriptLoader,<br \/>\nObjectUtils,<br \/>\n{<br \/>\nprovide: APP_INITIALIZER,<br \/>\nuseFactory: (configurationService: ConfigurationService, preBootScriptLoader: PreBootScriptLoader) =&gt; () =&gt; {<br \/>\n&nbsp;&nbsp;return configurationService.load().then(() =&gt; preBootScriptLoader.load);<br \/>\n},<br \/>\ndeps: [ConfigurationService, ConfigurationValidator, PreBootScriptLoader, ScriptLoader, ObjectUtils],<br \/>\nmulti: true<br \/>\n},<br \/>\n],<br \/>\nbootstrap: [AppComponent]<br \/>\n})<\/p>\n<\/blockquote>\n<p>Promise rejection code fragment showing passing an error in the reject:<\/p>\n<blockquote><p>if (this.configurationValidator.validate(appConfig)) {<br \/>\n&nbsp;&nbsp;console.error(&#8216;Configuration failed validation&#8217;, appConfig);<br \/>\n&nbsp;&nbsp;reject(new Error(&#8216;Configuration failed validation as above.&#8217;));<br \/>\n} else {<br \/>\n&nbsp;&nbsp;resolve();<br \/>\n}<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>This allows the use of asynchronous operations (such as configuration loading) at Angular bootstrap time. It is documented (somewhat minimally to say the least) here. In my case I needed it to allow early script loading of (in my case Yoti) external scripts at bootstrap time. A Yoti script overwrote some promise code that had [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[198,77],"tags":[],"_links":{"self":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2346"}],"collection":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2346"}],"version-history":[{"count":6,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2346\/revisions"}],"predecessor-version":[{"id":2352,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2346\/revisions\/2352"}],"wp:attachment":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2346"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2346"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2346"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}