2

I'm new at angular. Basically, my project is composed of several components. the first one is the loggin, where the menu is not shown, in the rest of the components yes (if the user has logged in). How to know if the user has logged in? it's easy, because when the login component logs in, it is stored in localstorage "iduser".

the logic that you will see next I am doing it from my app.component.ts.

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {

    showMenuEmitter = new EventEmitter<boolean>();
    showMenu: boolean;
    constructor(
            private router : Router
        ){
            console.log(this.router.url);

        if(!localStorage.getItem("idusuario")){
            this.showMenuEmitter.emit(true);
            this.router.navigate(["/"]);

        }

        else if(localStorage.getItem("idusuario") && this.router.url=="/"){
            this.router.navigate(["avance_entregables"]);
            this.showMenuEmitter.emit(false);
            console.log( this.showMenu );
        }
        this.showMenuEmitter.subscribe(
        mostrar => this.showMenu = mostrar
        );

    }
}

Here I am trying to establish whether or not to show the menu. and in app.component.html I would like to hide it or show it.

<menu *ngIf="showMenu"></menu>
<router-outlet></router-outlet>

I have never used EventEmitter, but I have looked for examples and apparently it would be the best practice. What am I doing wrong?

M Reza
  • 18,350
  • 14
  • 66
  • 71
unusuario
  • 151
  • 1
  • 13

3 Answers3

0

Change this.showMenuEmitter.emit(true/false); to

this.showMenu=true or false;  // Add this line with true or false value

and remove showMenuEmitter at all - because we usually use events to communication with other components but not usually inside component which emit event

UPDATE (comments)

Add following code to constructor (we will subscribe any router changes and refresh state of showMenu to proper - add Event to import statment at file header)

router.events.subscribe((event: Event) => {
    this.showMenu=true;  // or true
    if(localStorage.getItem("idusuario")) this.showMenu=false;  // or false
});
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
  • apparently it works But if after this I navigate to my login, the menu will appear and that is precisely what I need to avoid. – unusuario Jan 21 '19 at 04:26
  • I have listened to you. It works when I open my web app for the first time. but if I logout or login I do not update. – unusuario Jan 21 '19 at 04:31
  • @unusuario when you logout- do you delete `idusuario` from localStorage? – Kamil Kiełczewski Jan 21 '19 at 04:32
  • @unusuario When you put `console.log(localStorage.getItem("idusuario"))` before `if(!localStorage.getItem("idusuario"))` what do you see on console after logout? Debugg it in this way – Kamil Kiełczewski Jan 21 '19 at 04:36
  • depends.. if the user is login, the response is 15. if not is login is null. but since this is in the app.component this validation is done the first time. – unusuario Jan 21 '19 at 04:40
  • in this way it will not be updated, it is not reactive. this is executed only once – unusuario Jan 21 '19 at 04:53
  • https://i.imgur.com/2LTSDx0.jpg I do not think it's a good way, it runs many times. – unusuario Jan 21 '19 at 05:14
  • @unusuario - yes it will run allways when routing is change - and detect the state (user is login or not). This is very simple and fast code, so run it on every routing change is acceptable. However maybe exists better solution - but I don't know it – Kamil Kiełczewski Jan 21 '19 at 05:17
  • @unusuario in your screenshot there is a bug - you twice set `showMenu` to true (below console.log('eu') ) – Kamil Kiełczewski Jan 21 '19 at 05:18
  • I have corrected it, but I mean that this is executed many times. look at the part on the right in the console. – unusuario Jan 21 '19 at 05:20
0

It's a more common practice to use a Subject and Observable. This article explains how to do that more. Generally people don't use an eventEmitter unless they're outputting values from child components via (), but it does happen and I'm not going to say it's right or wrong. You actually have a pretty cool example of it :) Back to the Observable, you can do your if *ngIf="obsName | async" and it'll show/hide the menu as needed when it's observed value (the subject) changes without the need to manually adjust the layout's state.

  • As I understand it, is it intended to create the localstorage variable as an observable? I think this would fit a good solution, I would like to fix everything from app.component. The other response of another user works partially. This example that you put is something advanced for me, I do not understand it well. – unusuario Jan 21 '19 at 04:33
0

You need a Shared Service.

1) create shared.service.ts (like simple service)

2) in this service define variable as BehaviorSubject

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

@Injectable()
export class DataService {

  private _currentAuth = new BehaviorSubject(false);
   currentAuth= this._currentAuth.asObservable();

  constructor() { }

  changeAuth(auth: boolean) {
    this.currentAuth.next(auth)
  }

}

3) add this service as provider in module that is common for all components (app.module.ts)

4) now you can set shared service variable in components:

this.service.changeAuth(true);

and you can subsribe to currentAuth value to get value:

 this.service.currentAuth.subscribe(serviceValue => this.showMenu = serviceValue );

Auth value from service will be the same for all components. And you can easily check the user status. In shared.service.ts you can create checkStatus() where you will subscribe from another service from localhost