Sending data from the LoginComponent to the RootComponent

I am facing a challenge with implementing *ngIf to hide the login/logout option in the navbar based on the user's authentication status. When logged in, I want to hide the logout link. Here is my current setup.

app.component.ts

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

import { UserService } from './user';
import { Router } from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
  title = 'app works!';

  loginstatus: boolean = false;

  constructor(private _userService: UserService, private _router: Router){}

  onLogout(){
    this._userService.logout();
    this._router.navigate(['/login']);
  }

  ngOnInit(){
    this.onLogout();
  }
}

app.component.html

<ul class="navigation">
  <li *ngIf="!loginstatus"><a routerLink="/login" routerLinkActive="active">Login</a></li>
  <li *ngIf="loginstatus"><a (click)="onLogout()">Logout</a></li>
</ul>

<router-outlet></router-outlet>

login.component.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators} from '@angular/forms';

import { UserService } from '../user.service';

@Component({
    selector: 'login',
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.css']
})

export class LoginComponent implements OnInit{
    user = {
        username: '',
        password: ''
    }

    loginForm: FormGroup;

    constructor(private _userService: UserService, private _formBuilder: FormBuilder){}

    ngOnInit(){
        this.loginForm = this._formBuilder.group({
            username: ['', Validators.required],
            password: ['', Validators.required]
        });
    }

    onLogin(){
        this._userService.postUserLogin(this.user)
            .subscribe(token => {
                console.log(localStorage.getItem('currentUser'));
            })
            err => console.log(err);
    }
}

In my code snippet, the variable loginstatus determines the user's authentication state for hiding the login option. Now, my question is, how can I update the value of loginstatus from the login component to control the visibility of the login option in the navbar?

Answer №1

The primary issue at hand is the need for a notification when a value changes rather than simply sharing the value itself. This can be achieved by implementing an event system using tools like EventEmitter, rxjs, or standard Angular change detection with ngOnChanges.

For example, you can create an RX subject:

export const loginStatusChanged = new BehaviorSubject<boolean>(false);

This sets the default state as user not being logged in.

In the app.component, you can subscribe to the event:

import { loginStatusChanged } from ...;

...

loginStatus: boolean;

...

ngOnInit() {
  loginStatusChanged.subscribe(status => this.loginStatus = status);
}

In the login.component:

...
// when logged in
loginStatusChanged.next(true);
...

Although it may be argued that utilizing a service would be better practice, in this case, it functions effectively and is easily unit-testable even without dependency injection.

Just a quick note: if it were not the AppComponent, it would be advisable to unsubscribe from the observable or consider using ng2-rx-collector. In this scenario, it's not essential since AppComponent is only destroyed when shutting down the entire application.

Answer №2

One strategy to facilitate communication between your LoginComponent and AppComponent is by creating a shared service that can be accessed by both components. This allows for seamless interaction between the two components. For more information on how to implement this, refer to the documentation on Parent and children communicate via a service.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing TypeScript path aliases in a Create React App project with TypeScript and ESLint: A step-by-step guide

I utilized a template project found at https://github.com/kristijorgji/cra-ts-storybook-styled-components and made some enhancements. package.json has been updated as follows: { "name": "test", "version": "0.1.0" ...

Using templateUrl from a remote server in Angular 2 can be achieved by specifying the complete URL

My file contains the following component with a remote URL: @Component({ templateUrl: '/mobilesiteapp/template/?path=pages/tabs' }) export class TabsPage { } Unfortunately, when compiling, I encountered this error message: [13:28:50] Error ...

The firebase-admin module encounters compatibility issues with middleware due to the OS Module

I'm facing a major issue with my API implementation. I am working on integrating an authentication and verification middleware, but the problem arises when using firebase-admin due to its dependencies on Edge Runtime modules that are incompatible with ...

Restrict the number of subscriptions allowed for an rxjs observable

Seeking a replacement for observable, subject, or event emitter that allows only one subscription at a time. The first subscriber should have priority to execute its subscribe function, with subsequent subscribers waiting their turn until the first unsubsc ...

Steps for creating an Observable<Object[]> using data from 2 different API requests

My goal is to retrieve an Observable<MyResult[]> by making 2 separate API calls to load the necessary data. The first call is to load MyItem. The second call is to load Gizmos[] for each item. In a previous question, I loaded the second API into t ...

Issue: Inadequate parameters have been supplied for the localized pathname (getPathname()). This problem arose after the inclusion of "next-intl/routing" module

After implementing the config file and replacing : Navigation File import { createLocalizedPathnamesNavigation, Pathnames } from 'next-intl/navigation'; With : Config File import {Pathnames, LocalePrefix} from 'next-intl/routing';} ...

Issue: The UserComponent is attempting to set the property 'id' of an undefined object, resulting in an error

An error has occurred indicating that the property 'id' cannot be set as it is undefined in the UserComponent file of user.component.ts. Here is the TypeScript code: import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, Rou ...

Tracking events in Angular 4 using angulartics2 and Adobe Analytics: A step-by-step guide

I've been working on tracking page views in my Angular 4 application, specifically with Adobe Analytics. Currently, I am utilizing angulartics2 for this purpose. First step was adding the necessary script for Adobe Staging in my index.html page: &l ...

Looking for the final entry in a table using AngularJS

Hey everyone, I'm dealing with a table row situation here <tbody> <tr *ngFor="let data of List | paginate : { itemsPerPage: 10, currentPage: p }; let i = index"> <td>{{ d ...

Investigating sibling HTML elements using an Angular directive

When working with Angular 10, my goal is to access a sibling element within my directive. This is illustrated by the following code snippet: <label myDirective for="foo" ... <input id="foo" formControlName="xyz" ... Wit ...

a search-enabled dropdown menu within an Angular input field

I can't seem to get the input box to display in my code below. Can you help me figure out why? component.html <form [formGroup]="formGroup" (validSubmit)="onSubmit()"> <div class="form-group mb-3"> ...

Changing a d3 event from JavaScript to Typescript in an Angular2 environment

I am a beginner in Typescript and Angular 2. My goal is to create an Angular2 component that incorporates a d3js tool click here. However, I am facing challenges when it comes to converting it to Typescript. For instance, I am unsure if this code rewrite ...

Using React and Typescript: How do I properly type a button that occasionally uses "as={Link}"?

I've encountered a scenario where I have a versatile button component that can either function as a button or transform into a link for enhanced user experience by using to={Link}. The challenge arises when Typescript always interprets the button as a ...

Is it possible to use Firebase auth.user in order to retrieve the signed-in user directly?

As I develop a webapp with NextJS v13.4 and firebase as my backend using the firebase web modular api, I came across a statement in the documentation: "The recommended way to get the current user is by setting an observer on the Auth object." ...

Using AngularFire2 to manage your data services?

After diving into the resources provided by Angular.io and the Git Docs for AngularFire2, I decided to experiment with a more efficient approach. It seems that creating a service is recommended when working with the same data across different components in ...

Ways to declare the function prototype using object and key as parameters

I am currently working on defining a utility function that will handle axios errors and store the resulting error message into a specific field of a specified object. The desired syntax for using this function is: axios.get(...).then(...).catch(ParseIntoE ...

Implementing a 12-month display using material-ui components

Just starting out with ReactJs, TypeScript, and material-ui. Looking to display something similar to this design: https://i.stack.imgur.com/zIgUH.png Wondering if it's achievable with material-ui. If not, any suggestions for alternatives? Appreciate ...

Imported modules are not being blocked by APP_INITIALIZER

In my Angular application (version 6.0.0), I am working on setting up runtime configuration using APP_INITIALIZER to pull in the configurations. While consulting various articles and Stack Overflow questions, such as this one and that one, I have managed t ...

Encountering the message "npm ERR! missing script: start" following the update to .Net 3.0

Previously, the ASP.Net Core 2.2 code (upgraded from 2.1) did not include a start script in package.json. https://github.com/TrilonIO/aspnetcore-angular-universal/blob/master/package.json Upon upgrading to ASP.Net Core 3.0, it now requires a start script ...

Combining TypeScript and JavaScript for efficient mixins

I came across an article on MDN discussing the usage and creation of mix-ins (link). Intrigued, I decided to try implementing it in TypeScript: type Constructor = new (...args: any) => any; function nameMixin(Base: Constructor) { return class extends ...