13

I am trying to make User Authentication with Angular and ASP.NET Core.

I am following the tutorial found here:

https://fullstackmark.com/post/10/user-authentication-with-angular-and-asp-net-core

I followed all the steps with no errors.

The app runs, but when I go to "/register" or "/login" routes, I get

NodeInvocationException: Uncaught (in promise): ReferenceError: localStorage is not defined
ReferenceError: localStorage is not defined

the service that uses it is:

import { Injectable, Inject } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';

import { UserRegistration } from '../shared/models/user.registration.interface';
import { ConfigService } from '../shared/utils/config.service';

import { BaseService } from "./base.service";

import { Observable } from 'rxjs/Rx';
import { BehaviorSubject } from 'rxjs/Rx';

//import * as _ from 'lodash';

// Add the RxJS Observable operators we need in this app.
import '../rxjs-operators';

@Injectable()
export class UserService extends BaseService {

  baseUrl: string = '';

  // Observable navItem source
  private _authNavStatusSource = new BehaviorSubject<boolean>(false);
  // Observable navItem stream
  authNavStatus$ = this._authNavStatusSource.asObservable();

  private loggedIn = false;

  constructor(private http: Http, private configService: ConfigService) {
    super();
    this.loggedIn = !!localStorage.getItem('auth_token');
    // ?? not sure if this the best way to broadcast the status but seems to resolve issue on page refresh where auth status is lost in
    // header component resulting in authed user nav links disappearing despite the fact user is still logged in
    this._authNavStatusSource.next(this.loggedIn);
    this.baseUrl = configService.getApiURI();
  }

    register(email: string, password: string, firstName: string, lastName: string,location: string): Observable<UserRegistration> {
    let body = JSON.stringify({ email, password, firstName, lastName,location });
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });

    return this.http.post(this.baseUrl + "/accounts", body, options)
      .map(res => true)
      .catch(this.handleError);
  }  

   login(userName: any, password: any) {
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');

    return this.http
      .post(
      this.baseUrl + '/login',
      JSON.stringify({ userName, password }),{ headers }
      )
      .map(res => res.json())
      .map(res => {
        localStorage.setItem('auth_token', res.auth_token);
        this.loggedIn = true;
        this._authNavStatusSource.next(true);
        return true;
      })
      .catch(this.handleError);
  }

  logout() {
    localStorage.removeItem('auth_token');
    this.loggedIn = false;
    this._authNavStatusSource.next(false);
  }

  isLoggedIn() {
    return this.loggedIn;
  }  
}

the register ts is:

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

import { UserRegistration } from '../../shared/models/user.registration.interface';
import { UserService } from "../../services/user.service";

declare var localStorage: any;

@Component({
  selector: 'app-registration-form',
  templateUrl: './registration-form.component.html'
})
export class RegistrationFormComponent implements OnInit {

 errors: string;  
 isRequesting: boolean;
 submitted: boolean = false;

 constructor(private userService: UserService, private router: Router) { 

 }

  ngOnInit() {

  }

  registerUser({ value, valid }: { value: UserRegistration, valid: boolean }) {
     this.submitted = true;
     this.isRequesting = true;
     this.errors='';
     if(valid)
     {
         this.userService.register(value.email,value.password,value.firstName,value.lastName,value.location)
                   .finally(() => this.isRequesting = false)
                   .subscribe(
                     result  => {if(result){
                         this.router.navigate(['/login'],{queryParams: {brandNew: true,email:value.email}});                         
                     }},
                     errors =>  this.errors = errors);
     }      
  }  
}

the login is:

import { Subscription } from 'rxjs';
import { Component, OnInit,OnDestroy } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';

import { Credentials } from '../../shared/models/credentials.interface';
import { UserService } from '../../services/user.service';

@Component({
  selector: 'app-login-form',
  templateUrl: './login-form.component.html'
})
export class LoginFormComponent implements OnInit, OnDestroy {

  private subscription: Subscription;

  brandNew: boolean;
  errors: string;
  isRequesting: boolean;
  submitted: boolean = false;
  credentials: Credentials = { email: '', password: '' };

  constructor(private userService: UserService, private router: Router,private activatedRoute: ActivatedRoute) { }

    ngOnInit() {

    // subscribe to router event
    this.subscription = this.activatedRoute.queryParams.subscribe(
      (param: any) => {
         this.brandNew = param['brandNew'];   
         this.credentials.email = param['email'];         
      });      
  }

   ngOnDestroy() {
    // prevent memory leak by unsubscribing
    this.subscription.unsubscribe();
  }

  login({ value, valid }: { value: Credentials, valid: boolean }) {
    this.submitted = true;
    this.isRequesting = true;
    this.errors='';
    if (valid) {
      this.userService.login(value.email, value.password)
        .finally(() => this.isRequesting = false)
        .subscribe(
        result => {         
          if (result) {
             this.router.navigate(['/home']);             
          }
        },
        error => this.errors = error);
    }
  }
}

I tried the solution from:

localStorage is not defined (Angular Universal)

but it does not work...

What am I missing

Rakesh Chand
  • 3,105
  • 1
  • 20
  • 41
Andrei Dobrin
  • 1,164
  • 4
  • 19
  • 35

4 Answers4

5

You can use standard API for localstorage, like

localStorage.setItem(key, val)

and

localStorage.getItem(key)

but If you want a angular solution for this and find a good library for localstorage, one I'm using is this

https://github.com/marcj/angular2-localstorage

also

https://www.npmjs.com/package/angular2-cool-storage

is cool to use.

Rashed Rahat
  • 2,357
  • 2
  • 18
  • 38
Rakesh Chand
  • 3,105
  • 1
  • 20
  • 41
  • 2
    yes, but why am I getting this error? P.s. my project can be found here https://github.com/dobrinsky/AngularDefault – Andrei Dobrin Sep 06 '17 at 10:55
  • angular2-localstorage says it is no longer being maintained. – java-addict301 Apr 09 '19 at 11:37
  • @java-addict301 you can use the standard service localstorage of js or there are other good libararies as well like `ngx-webstorage-service` or `angular-webstorage-service`, if you understand how to use the native service than no need to use external libabry for it. cheers, hope i helped – Rakesh Chand Apr 16 '19 at 16:05
3

The standard localStorage API should be available.

No need to declare it.

to set localStorage.setItem('name', 'storingSomething');

to get localStorage.getItem('name');

k11k2
  • 2,036
  • 2
  • 22
  • 36
2

You are probably getting this error because the component is looking for localStorage when rendering server side, which is why it cannot be found and you are getting this error message.

I had a similar problem in React and solved it by simply importing the component dynamically, disabling SSR. Even just disabling SSR should be fine, you can choose whether to do this on import or export.

Hope this solves your problem

Nicola Gaioni
  • 168
  • 2
  • 8
0

Put localStorage.getItem(...) on `ComponentDidMount()``

Norbert Bartko
  • 2,468
  • 1
  • 17
  • 36
D.Quang
  • 11