web-dev-qa-db-fra.com

Angular.io / Angular 4. Comment actualiser une vue de composant lors du déclenchement d'une autre

J'ai une application simple Angular.io. (angular-cli/4.1.0) 

J'ai un NavbarComponent qui rend le nom d'utilisateur.

Lors de la première utilisation de l'application, je ne suis pas connecté et mon application redirige le composant de connexion. Ma barre de navigation est également rendue, mais sans nom d'utilisateur. Une fois la connexion établie, je suis redirigé vers mon HomeComponent.

Et voici le problème. Ma NavBar n'affiche pas le nom d'utilisateur. Mais si je fais une actualisation/ctrl + r le nom d'utilisateur est rendu.

Qu'est-ce qui ne va pas?

app.component.html

<nav-bar></nav-bar>
<router-outlet></router-outlet>

navbar.compoment.ts

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

@Component({
  selector: 'nav-bar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {

  me;

  ngOnInit() {
    this.me = JSON.parse(localStorage.getItem('currentUser'));
  }
}

login.component.ts

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

import { AlertService, AuthenticationService } from '../_services/index';

@Component({
    moduleId: module.id,
    templateUrl: 'login.component.html'
})

export class LoginComponent implements OnInit {
    model: any = {};
    loading = false;
    returnUrl: string;

    constructor(
        private route: ActivatedRoute,
        private router: Router,
        private authenticationService: AuthenticationService,
        private alertService: AlertService) { }

    ngOnInit() {
        // reset login status
        this.authenticationService.logout();

        // get return url from route parameters or default to '/'
        this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
    }

    login() {
        this.loading = true;
        this.authenticationService.login(this.model.email, this.model.password)
            .subscribe(
                data => {
                    this.router.navigate([this.returnUrl]);
                },
                error => {
                    this.alertService.error(error);
                    this.loading = false;
                    this.errorMsg = 'Bad username or password';console.error('An error occurred', error);
                });
    }
}
5
ChrisWorks

Comme mentionné par JusMalcolm, OnInit ne s'exécute plus.

Mais vous pouvez utiliser Subject pour indiquer à NavbarComponent d'extraire les données de la mémoire de stockage locale.

Dans votre NavBarComponent import Subject et déclarez-le:

import { Subject } from 'rxjs/Subject';

....

public static updateUserStatus: Subject<boolean> = new Subject();

Alors abonnez-vous à votre constructeur:

constructor(...) {
   NavbarComponent.updateUserStatus.subscribe(res => {
     this.me = JSON.parse(localStorage.getItem('currentUser'));
   })
}

Et dans votre LoginComponent, importez votre NavbarComponent et lorsque vous vous êtes connecté avec succès, appelez simplement next() sur le sujet et NavbarComponent y sera abonné.

.subscribe(
   data => {
      NavbarComponent.updateUserStatus.next(true); // here!
      this.router.navigate([this.returnUrl]);
   },
   // more code here

Vous pouvez également utiliser un service partagé pour indiquer à NavbarComponent de réexécuter la récupération de l'utilisateur. En savoir plus sur le service partagé du Documents officiels .

6
AJT_82

Comme le composant a déjà été initialisé, ngOnInit () ne s'exécute pas après la connexion. Une solution à votre cas consiste à vous abonner à un paramètre de routeur qui vérifie si l'utilisateur est connecté. 

par exemple.

this.route.queryParams
        .map(params => params['loggedIn'])
        .subscribe(loggedIn => {
            if (loggedIn) {
                this.me = JSON.parse(localStorage.getItem('currentUser'));
            }
        });
0
JusMalcolm

Si vous pouvez renvoyer le nom depuis le backend lors de l'authentification, vous pouvez injecter AuthenticationService à NavbarComponent et lier le nom requis dans navbar.component.html.

NavbarComponent:

export class NavbarComponent {
   ...
   constructor(private authservice: AuthenticationService) {}
   ...
}

navbar.component.html:

<span>Welcome {{authservice.name}}!</span>
0
GKK