Expressingx
Expressingx

Reputation: 1572

Where to store global data in Angular?

I decided to learn Angular 4 and ASP Net Core 2 at once by building blog application. I came to a point where I want to store global data for every component.

For example, I want when the user logs in to pass the logged state to my navbar component and by that I can change the buttons, show the current user name etc.

How from my LoginComponent I can pass data to my NavbarComponent and so on?

Upvotes: 14

Views: 45845

Answers (4)

Gaurav Singla
Gaurav Singla

Reputation: 1

There are two scenarios for data you want to share:

  1. If the data is changing dynamically and ofc you would want it to update everywhere throughout the application then NgRx is the way to go.
  2. Otherwise use services.

Upvotes: 0

celikz
celikz

Reputation: 111

Generally it is good practice to keep username at localStorage, i think.

so this Appservice subscribing to Webservice

import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

@Injectable()
export class AppService {
  protected authHeaders = new Headers({'Authorization': localStorage['accessToken']});
  protected headers = new Headers(this.authHeaders);

  constructor(protected http: Http) {
    this.headers.append('Content-Type', 'application/json');
  }

  login(username: string, password: string): Observable<string> {
    let info = JSON.stringify({username: username, password: password});
    return this.http.post('/login', info, {headers: this.headers})
      .map(res => res.headers.get('Authorization'))
      .catch(this.handle);
  }
}

and here is component

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import { AppService } from '../app.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
  private username: string;
  private password: string;
  private showErrorMessage: boolean = false;

  constructor(private service: AppService, private router: Router) { }

  ngOnInit() {
    if (localStorage.getItem('accessToken')) this.router.navigate(['/Home']);
  }

  login() {
    this.service.login(this.username, this.password).subscribe(
      data => {
        localStorage.setItem('userName', this.username);
        localStorage.setItem('accessToken', data);
        this.router.navigate(['/Home']);
      },
      () => { this.showErrorMessage = true }
    );
  }
}

Upvotes: 3

Lucas
Lucas

Reputation: 10313

Stackblitz with example of how to apply observable and @Input data changes accross components with a service.

You will need a service and Rxjs with subscriptions to do it the angular way:

import {Injectable}             from '@angular/core';
import {Subject}                from 'rxjs/Subject';

@Injectable()
export class UserNameService {

    execChange: Subject<any> = new Subject<any>();

    constructor() {}

    /**
     * Use to change user name 
     * @data type: string
     */
    userNameChange(data: string) {
        this.execChange.next(data);
    }
}

And then in every component where you want to have the user name changed add a subscription:

constructor(private userNameService : UserNameService) {
        this._subscription_user_name = this.userNameService.execChange.subscribe((value) => {
            this.userName= value; // this.username will hold your value and modify it every time it changes 
        });
}

How to change the value so that every subscription can moddify the values? Call your execChange function in your service:

this.userNameService.userNameChange('Thor');

EDIT: @Vikas comment is correct and quite self explanatory... youn need to add the service to ngModule providers array or you will get a headache dealing with unknown provider errors.

@NgModule({
  imports: [
    ...
  ],
  declarations: [...],
  providers: [UserNameService]
})

If you need to persist your data across tabs or when refreshing the page, use localstorage as well.

Upvotes: 23

tilo
tilo

Reputation: 14169

It might be overkill for starting to learn Angular, but as @ShellNinja pointed out, you might consider a library offering state management, e.g. ngrx.

From the @ngrx/store docs:

RxJS powered state management for Angular applications, inspired by Redux

@ngrx/store is a controlled state container designed to help write performant, consistent applications on top of Angular. Core tenets:

State is a single, immutable data structure. Actions describe state changes. Pure functions called reducers take the previous state and the next action to compute the new state. State accessed with the Store, an observable of state and an observer of actions. These core principles enable building components that can use the OnPush change detection strategy giving you intelligent, performant change detection throughout your application.

Upvotes: 3

Related Questions