3

Does anyone know a way that I can pass initialization data into an Angular 2 application built with Angular CLI? I need to pass Access Token that I currently have from a pre-authenticated .NET backend so that I can call an API.

I've tried to do this via a local web api endpoint, but since Observables are async, the module tries to use the value before it's available in the app.

I've already tried the OnRun suggestion by @Ben Nadel Here. The result of my http call still happens AFTER the app is loaded causing my access token to be null when it first is loaded.

Something like @Bilyachat suggested below would work great! Where I could simply do something like the following:

<app-root [apiKey]="1234567890xxxxx"></app-root>

Any help would be awesome... Thanks.

Mike Kushner
  • 959
  • 9
  • 14
  • "but I run into the async problem again." please post the code and explain what problem you run into. – Günter Zöchbauer Feb 22 '17 at 06:51
  • I've updated the question. Basically, I need that API key to start with to do any of the pages in a secured application. I already have the key from the server and need a way to pass it to the app. – Mike Kushner Feb 22 '17 at 14:21
  • I don't see anything about `OnRun`. What code did you use, what problem did it cause? – Günter Zöchbauer Feb 22 '17 at 14:22
  • I tried to initialize a user configuration via an http api endpoint by following Ben Nadel's instructions on [https://www.bennadel.com/blog/3180-ngmodule-constructors-provide-a-module-level-run-block-in-angular-2-1-1.htm] the classes OnRun methods are called, but since they are async, the APIKey comes in AFTER I need it in my application. I can't paste the code for some reason. – Mike Kushner Feb 22 '17 at 14:30
  • I got that. Without seeing the exact code you were using, I can't tell what's wrong with the code. See also http://stackoverflow.com/questions/37611549/how-to-pass-parameters-rendered-from-backend-to-angular2-bootstrap-method/37611614#37611614 – Günter Zöchbauer Feb 22 '17 at 14:33
  • I've put together a simple call out to JSONPlaceholder to see what I'm trying to do... [Please See This Plunkr](https://plnkr.co/edit/QI6VQq0vC0hBlWNx1KoJ?p=preview) – Mike Kushner Feb 22 '17 at 16:52
  • If you use `{}` `return` is required in `return config.load();` – Günter Zöchbauer Feb 22 '17 at 16:53
  • Note that I'm clearing the sessionStorage each time the page loads to display the issue on the index.html page with the following code – Mike Kushner Feb 22 '17 at 16:53
  • https://plnkr.co/edit/1u2iGwitnXhSA9LTFJds?p=preview seems to work fine – Günter Zöchbauer Feb 22 '17 at 16:56
  • OMG... I was missing a `return`... Thank you Günter Zöchbauer. I've updated the PlunkR and made it public for others to learn. [http://plnkr.co/kXNGj2](http://plnkr.co/kXNGj2) – Mike Kushner Feb 22 '17 at 17:08
  • Is there a way to mark your comment as an answer, or link this to your other answer? – Mike Kushner Feb 22 '17 at 17:09

4 Answers4

3

If you use {}, an explicit return is required in return config.load();

  useFactory: (config: AppConfig) => () => {
    return config.load();
  },

Plunker example

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Hi Gunter, is it possible to have two app Initializers and the second initializer waits untill the first one gets completed? I have a config service that returns all the urls for my app that runs APP_INITIALIZER. I also have a localizaiton module and provider that cannot be loaded until the first config for the localization has ran which contains an api endpoint returned from the config service. – crh225 May 15 '17 at 21:30
  • I don't think so, but you can combine them into a single one and wire them up so the 2nd waits for the first – Günter Zöchbauer May 16 '17 at 03:26
  • 3
    That is what I ended up doing. Thank you for your strong angular support. I know the community appreciates it! – crh225 May 16 '17 at 13:38
1

If you have angular app on MVC page then i see two options

First In angular root component attribute (In first suggestion i told you to use input parameters, but problem is that root component is "Out of angular" and it will not be able to read parameters the only way is to read attributes manually)

import {Component, NgModule, Input, ElementRef} from '@angular/core'
export class App {
   myConfig: any;
  constructor(element: ElementRef) {
    this.myConfig = element.nativeElement.getAttribute('data-config'); 
  }

}

Then when you print you can do like this

<app-root data-config="valueGoeshere"></app-root>

Updated plnkr

Second

Print on mvc page

var yourAppMvcConfig= {
    configValue: 'DO_PRINT_HERE'
};

add into src/typings.d.ts (If its missing add it)

declare var yourAppMvcConfig: {
    configValue: string;
}

Use in Angular

yourAppMvcConfig.configValue
Vova Bilyachat
  • 18,765
  • 4
  • 55
  • 80
  • Thanks Volodymyr, I tried to do your first suggestion and couldn't get it to work. I made a [Plunkr for it Here](https://plnkr.co/edit/46rXGzmtd5JRf8GQFxNg?p=preview) to show you. – Mike Kushner Feb 22 '17 at 14:00
  • And Typings.d.ts don't exist in new CLI projects. Some say they are deprecated while googling. – Mike Kushner Feb 22 '17 at 14:03
  • Love it... I got it working both ways now... Your first way is very much cleaner, IMO, compared to using APP_INITIALIZER when bootstrapping. Especially since I already have the values to just throw in it. Thanks to all. – Mike Kushner Feb 22 '17 at 23:23
  • @MikeKushner It always good to know two ways :) because some times there could be cases where you can use one or another :) or both together – Vova Bilyachat Feb 22 '17 at 23:24
  • @VovaBilyachat : Can you please take a look at https://stackoverflow.com/questions/66785098/passing-bearer-token-to-a-different-app-initializer-to-load-config-from-server-i . I would really really appreciate your guidance – Samuel Mar 24 '21 at 16:26
0

"the module tries to use the value before it's available in the app" - I think this is your problem.

Instead delaying the loading of the page until the call with your token has returned, why don't you write code that doesn't make any calls until the token has returned?

ngOnInit() {
    this.tokenService.getToken().subscribe((token) => {
        console.log('now I have a token, and am ready to make my calls', token);

        this.secureService.getSecureDataUsingToken(token).subscribe((result) => {
            console.log('here is the result of the authenticated call', result);
        }
    });
}
paul
  • 21,653
  • 1
  • 53
  • 54
  • You're absolutely correct @paul, that would work, except I would have to repeat that logic on every component that uses a secureService.xxxMethod method. Still looking for a way to get that key right off the bat and use it at the service level rather than on the container level if possible. – Mike Kushner Feb 22 '17 at 14:35
  • Can you please take a look at https://stackoverflow.com/questions/66785098/passing-bearer-token-to-a-different-app-initializer-to-load-config-from-server-i . I would really really appreciate your guidance – Samuel Mar 24 '21 at 16:26
0

Here is a solution I found. Your index.html file right where angular starts to load your script files. you can add the following line:

<script type="text/javascript">localStorage.setItem("title", "<?php echo $title; ?>")</script>

This will place the data in localstorage on the client an you can retrieve inside your application. I was using php trying to initialize some content in an opencart store. this is a good way to pass the data in. If you are passing in a JSON you need to json.stringfy before you pass in. When you retrieve it from withing the application you need do json.parse

darrisb
  • 11
  • 3