1

Hi I am using the new alpha component router of angularjs2 https://angular.io/docs/ts/latest/guide/router.html

I have a modal that authenticate a user then creates a JWT in localstorage which holds the user's needed info.

My problem is that if the user is looking on the /home path there are stuff there that only visible to logged-in users, but after he log in through the modal he has to refresh the page so the components will refresh and show the correct logged-in information

Is there a way to tell angular2 to refresh all the components on the current path? like a page reload but without really reloading the whole page (I dont want to just hit the refresh button for the user)

Thanks in advance

EDIT: maybe there is a feature to FORCE REDIRECT when I try to redirect into a route I am already in?

EDIT2: Trying with observables

@Injectable()
export class UserService {
  private loggedInObservable;

    constructor(private http: Http) {
        this.loggedInObservable = Observable.of(this.checkIsLoggedIn());
    }

    checkIsLoggedIn() {
        let isLoggedIn = false;
        try {
            isLoggedIn = tokenNotExpired();
        } catch(e) {

        }
        console.log('returning:', isLoggedIn);
        return isLoggedIn;
    }


    login(model, cbSuccess=null, cbError=null, cbAlways=null) {
        serverPost(this, '/api/users/login', model, cbSuccess, cbError, cbAlways, (data)=> {
            localStorage.setItem("id_token", data.id_token);
            this.loggedInObservable.map((val) => console.log('HELLO?'));
        });
    }

    isLoggedInObservable() {
        return this.loggedInObservable;
    }
}

the map does NOTHING at all (the 'HELLO?' isn't being displayed), although the observer has a value the map function does not call anything.

Using the observer:

import {Component, OnInit, OnDestroy} from '@angular/core';
import {UserService} from '../../services/userservice';

@Component({
  selector: 'test-thing',
  template: require('./test-thing.html'),
  styles: [require('./test-thing.scss')],
  providers: [],
  directives: [],
  pipes: []
})
export class TestThing implements OnInit, OnDestroy{
    private isLoggedIn = false;
    private sub: any;

    constructor(private userService: UserService) {

    };

    ngOnInit() {
      this.sub = this.userService.isLoggedInObservable().subscribe(loggedIn => {
        this.isLoggedIn = loggedIn;
      });
    }

    ngOnDestroy() {
      this.sub.unsubscribe();
    }
}

The initial value is working as intended but when I try to change the value after a successful login (with map) nothing happens, nothing at all.

10
  • To update logged-in information it shouldn't be necessary to reload everything. If you update the data, the bound view will update because of Angular change detection. Commented Jun 22, 2016 at 17:24
  • @GünterZöchbauer The problem is that I set isLogged=x in the ngOnInit so the variable is passed by value and I have no way to change it when a different modal sets the localStorage to hold the session. Do you mean to use Observables? I would rather avoid forcing all the components to subscribe to a change but I guess it can work like that Commented Jun 23, 2016 at 11:31
  • I would use an observable. It's a much cleaner solution. You can subscribe to router parameter changes and the whole application gets updated automatically if you notify about the change at one place. Commented Jun 23, 2016 at 11:46
  • @GünterZöchbauer I dont want to reflect a change in the url when you are logged in or not, can I create an observable in a service? is there a way to automatically unsubscribing from an observable on NgDestroy or I must manually set it up for each component? Commented Jun 23, 2016 at 12:19
  • If you subscribe manually you need to unsubscribe manually. If you subscribe only in the template using the | async pipe, then you don't need to unsubscribe. Commented Jun 23, 2016 at 13:56

1 Answer 1

5

Ok so seems what I needed is a BehaviorSubject since you can push values into it,subscribe to it to get changes and it projects the last value it got the first time you subscribe to it which is exactly what I need.

My code is now as follows:
userservice.ts

import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import {serverPost} from '../../functions';
import {BehaviorSubject} from 'rxjs/BehaviorSubject'
import {tokenNotExpired} from 'angular2-jwt';

@Injectable()
export class UserService {
    private isLoggedInSubject: BehaviorSubject<boolean>;

    constructor(private http: Http) {
        this.isLoggedInSubject = new BehaviorSubject(this.checkIsLoggedIn());
    }

    get loggedInObservable() {
        return this.isLoggedInSubject.asObservable();
    }

    checkIsLoggedIn() {
        let isLoggedIn = false;
        try {
            isLoggedIn = tokenNotExpired();
        } catch(e) {

        }
        return isLoggedIn;
    }

    signUp(model, cbSuccess=null, cbError=null, cbAlways=null) {
        serverPost(this, '/api/users', model, cbSuccess, cbError, cbAlways, (data)=> {
            localStorage.setItem("id_token", data.id_token);
            this.isLoggedInSubject.next(this.checkIsLoggedIn());
        });
    }

    login(model, cbSuccess=null, cbError=null, cbAlways=null) {
        serverPost(this, '/api/users/login', model, cbSuccess, cbError, cbAlways, (data)=> {
            localStorage.setItem("id_token", data.id_token);
            this.isLoggedInSubject.next(this.checkIsLoggedIn());
        });
    }
}

And this is how I use it in a component:

export class TestComponent implements OnInit, OnDestroy{
    private isLoggedIn = false;
    private loginSub;

    constructor(private userService: UserService) {

    };

    ngOnInit() {
      this.loginSub = this.userService.loggedInObservable.subscribe(val => {
        this.isLoggedIn = val;
      });
    }

    ngOnDestroy() {
      this.loginSub.unsubscribe();
    }

}

This setup works perfectly for my needs.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for this example, used it in my project as wel!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.