JustLearning
JustLearning

Reputation: 3322

Passing global constants to angular 4 from ASP.NET MVC

I am shifting from Razor views to Angular 4, and trying to figure out how to pass global constants from the server to Angular without relying on Ajax calls.

So the server constants will be transaction status for example:

Id: 1->Active
Id: 2-> Inactive
Id: 3->Cancelled etc

So these statuses are saved in the db and are used to query various transactions, Thus will be required in lots of components

In Razor views, I used to pass these values together with the viewmodel. But in Angular currently I can see two options:

  1. Make Ajax calls in ngOnInit of each component that requires these constants
  2. Make a static model to hold these values

Option 1 increases the number of server calls by quite a bit -> so I am trying to avoid this.

Option 2 will require me to change status in multiple places in my application if a new status is added for example, which i am also not fond of.

I am looking for a way to send all my constants to Angular as the application loads or page is reloaded for example.

Upvotes: 1

Views: 211

Answers (3)

wessam yaacob
wessam yaacob

Reputation: 937

You need to use ReplaySubject

as per rxjs documentation

ReplaySubject:Represents an object that is both an observable sequence as well as an observer. Each notification is broadcasted to all subscribed

Look at this code snippet

export class GlobalConstants{
  Status:number[];
}

import { Observable, ReplaySubject } from 'rxjs';
import { GlobalConstants } from '../models/GlobalConstants';

@Injectable()
export class YourService {
       //This line will cache the latest list you will get from the server
  private dataSubject = new ReplaySubject<GlobalConstants>();

     //you will use this observer in your components to subscribe to the getStatus result 
  yourStatusList$: Observable<GlobalConstants> = this.dataSubject.asObservable();

  constructor(private http: Http) {
    this.getStatus()
  }
  getStatus() {
    return this.http.get('url').subscribe(res => {
      this.dataSubject.next(res);
    })
  }


export class ExampleComponent {

  public statusList;

  public constructor(private _yourService: YourService) {
    this.getStatus();
  }


  getStatus(): void {
    this._yourService.yourStatusList$.subscribe(
      result => {
        this.statusList = result;
      }
    )
  }
}

what will happen is when angular create the service it will call getStatus method one time per the app life cycle and then fetch your status list from the server then u will need to subscribe in your components to yourStatusList$ , for each subscrbition you will get latest cached list and if the list changed in your server u just need to call YourService.getStatus then u will fetch the status list again and all component subscribed to this observer will get notified by the new list

let's take your two challenges

1-Make Ajax calls in ngOnInit of each component that requires these constants

-by using this code your app will make one call to the server to fetch status list so u don't need to make Ajax call in ngOnInit of each component

2-Make a static model to hold these values will require me to change status in multiple places in my application if a new status is added

-if new status is added you just need to call YourService.getStatus one time in any place in your code and all components subscribed to your yourStatusList will get notified by the new status list

NOTE: you must n't use providers: [yourService] in your component cause if u used it it will create a new object and will not use the global object , just add your service in @NgModule providers and use component constructor to inject the service object

Upvotes: 2

KavehG
KavehG

Reputation: 323

You can add you constants as attributes on your app element inside you razor view

<app someatt="{ your json data here }">Loading...</app>

then on you app's root component access them like this:

export class AppComponent implements OnInit {
    constructor(
        private el: ElementRef
    ) {
    }
    ngOnInit() {
        console.log(this.el.nativeElement.attributes["someatt"].value);
    }
}

then you can have a global service with its statuses data set here on ngOnInit and consumed in all your components

Upvotes: 1

R. Richards
R. Richards

Reputation: 25161

It may be best to have a service cache the information in a local variable. Then, when you inject the service into your components, and one calls a service function, the service checks the local variable. If something is in the variable, use it, if not, load the data and cache it for later use.

Since the service is a singleton, the data should only load once unless you create some mechanism to timeout the value. So, the first time the service is called, the data will be fetched. After that, the local variable (below called globals) should be used.

Service:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class GlobalsService {
    private globals: any;
    constructor(private httpClient: HttpClient) { }

    getGlobals(): any {
        if (this.globals) {
            return this.globals;
        } else {
            // call your API to get global data from DB
            this.httpClient.get<any>('...').subscribe((data: any) => {
                this.globals = data;
                return this.globals;
            });
        }
    }
}

Component using the service:

import { GlobalsService } from './../globals.service';
import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'app-tester',
    templateUrl: './tester.component.html',
    styleUrls: ['./tester.component.css']
})
export class TesterComponent implements OnInit {

    constructor(private globalsService: GlobalsService) { }

    ngOnInit() {
        // Do something here with the globals from the service
        const gbls = this.globalsService.getGlobals();
        if (gbls) {
          // ... maybe put these in a variable for later use, what ever you need
        }
    }
}

Doing this will keep you from having to do the Ajax call you mention, and avoid you have to keep code in more than one place. The service pattern offers a nice central place to keep this data for the lifetime of the application. All you need to do is inject the service into the component, or other services, where it is needed.

Upvotes: 2

Related Questions