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

What could be causing the angular Data table to not display properly?

I am currently exploring Angular Datatables and have a question about re-rendering the datatable after it has been hidden. Can anyone provide guidance on how to achieve this? In my project, I have two components - Parent and Child - that can be hidden or ...

What is the process for consumers to provide constructor parameters in Angular 2?

Is it possible to modify the field of a component instance? Let's consider an example in test.component.ts: @Component({ selector: 'test', }) export class TestComponent { @Input() temp; temp2; constructor(arg) { ...

How can jsPDF be used with Angular2 in Typescript?

Recently, I developed an Angular2 application that is capable of generating JSON data. My main goal was to store this JSON output into a file, specifically a PDF file. This project was built using Typescript. To achieve the functionality of writing JSON d ...

Implementing Styled API in TypeScript with props: A Comprehensive Guide

I'm currently working on styling a component using the new styled API, not to be confused with StyleComponents. const FixedWidthCell = styled(TableCell)((props: { width: number }) => ({ width: props.width || 20, textAlign: "center", })) The i ...

Choosing the correct key and handling parsing errors

As I work on converting a class component to TypeScript, I encountered an error while trying to implement one of my onChange methods. The error message stated: "Argument of type '{ [x: number]: any; }' is not assignable to parameter of type &ap ...

Display a separate component within a primary component upon clicking a button

Looking to display data from a placeholder module upon component click. As a beginner with React, my attempts have been unsuccessful so far. I have a component that lists some information for each element in the module as a list, and I would like to be ab ...

Mastering Angular 2 Reactive Forms: Efficiently Binding Entire Objects in a Single Stroke

Exploring reactive forms in Angular 2 has led me to ponder the possibility of binding all object properties simultaneously. Most tutorials show the following approach: this.form = this.fb.group({ name: ['', Validators.required], event: t ...

Shattered raw emotion

Does anyone have any insight on how to resolve this error? I've hit a roadblock trying to figure out the issue in the message below. Here is the snippet of code: :label="` ${$t('cadastros.clientes.edit.status')}: ${cliente.status === ...

Angular 6 - Ensuring all child components are instances of the same component

My issue has been simplified: <div *ngIf="layout1" class="layout1"> <div class="sidebar-layout1"> some items </div> <child-component [something]="sth"></child-component> </div> <div *ngIf="!layout1" class= ...

How do I manage 'for' loops in TypeScript while using the 'import * as' syntax?

When working with TypeScript, I encountered an issue while trying to import and iterate over all modules from a file. The compiler throws an error at build time. Can anyone help me figure out the correct settings or syntax to resolve this? import * as depe ...

Utilizing Angular Forms for dynamic string validation with the *ngIf directive

I have a challenge where I need to hide forms in a list if they are empty. These forms contain string values. I attempted to use *ngIf but unfortunately, it did not work as expected and empty fields are still visible in the list. How can I address this iss ...

When using Angular and Express together, the session is not continuous as each new request generates a fresh session

Unique Question I have encountered an issue with passport.js while trying to implement authentication in my express application. When I use req.flash('message', 'message content') within a passport strategy, the flashed information see ...

Can TypeScript provide a method for verifying infinite levels of nested arrays within a type?

Check out this example The concept behind this is having a type that can either be a single object or an array of objects. type SingleOrArray<T> = T | T[]; The structure in question looks like this: const area: ItemArea = [ { name: 'test1& ...

Embarking on your ABLY journey!

Incorporating https://github.com/ably/ably-js into my project allowed me to utilize typescript effectively. Presently, my code updates the currentBid information in the mongodb document alongside the respective auctionId. The goal is to link the auctionId ...

Changing dates in JavaScript / TypeScript can result in inaccurate dates being displayed after adding days

Recently, I encountered an issue with a simple code snippet that seems to produce inconsistent results. Take a look at the function below: addDays(date: Date, days: number): Date { console.log('adding ' + days + ' days'); con ...

Instructions on how to post an array by its ID when the value changes in the form, correspond with the ID

Whenever I change the value in the radio button within a form popup, I want to trigger this action. Below is the corresponding HTML code: <ng-container cdkColumnDef="injected"> <mat-header-cell *cdkHeaderCellD ...

Having trouble making API calls from the NextJS endpoint

While attempting to access an external API endpoint in NextJS, I encountered the following error message: {"level":50, Wed Jan 24 2024,"pid":4488,"hostname":"DESKTOP-S75IFN7","msg":"AxiosError: Request ...

Unexpected behavior: Angular4/Javascript Date object alters when timezone is specified in Date constructor

In my Angular 4 application, I encountered an issue with a date retrieved from an API call. The date is in the format '1990-03-31T23:00:00-06:00' and when attempting to create a Date object and retrieve the month using getMonth(), it returns the ...

Tips for prohibiting the use of "any" in TypeScript declarations and interfaces

I've set the "noImplicitAny": true, flag in tsconfig.json and "@typescript-eslint/no-explicit-any": 2, for eslint, but they aren't catching instances like type BadInterface { property: any } Is there a way to configure tsco ...

Using Vue in conjunction with TypeScript and CSS modules

I am facing an issue with my SFC (single file vue component) that utilizes TypeScript, render functions, and CSS modules. <script lang="ts"> import Vue from 'vue'; export default Vue.extend({ props: { mode: { type: String, ...