0
votes

How to show/hide HTML content after the component has been loaded?

I'm trying to show/hide a button on the header toolbar that changes depending on the login state.

The toolbar component below is loaded in the home page. Since the component is loaded on home page, it never gets reloaded again. When I login, I want to show and hide that ion-buttons section accordingly.

After login, I've called the getAndSetLogin() function in my toolbar component class and the console log shows loggedIn=true, which should now hide the login section, but that doesn't show/hide.

Toolbar Component HTML

<ion-header>
  <ion-toolbar>
    // Hide this button if logged in
    <ion-buttons *ngIf="!loggedIn" slot="end">
      <ion-button (click)="showLoginPopover($event)">
        <ion-label class="header-toolbar-text btn-label">Log In</ion-label>
      </ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

(Toolbar Component.ts) Function to update login state in toolbar component

  public getAndSetLoginState() {
    this.userService.checkedLoggedInStatus().subscribe((loggedInState: any) => {
      // loggedInState is either true or false, true if logged in and false otherwise
      this.loggedIn = loggedInState;
    });
  }

The above code from Toolbar component file is trigger when I login, which right now is just a button in a provider that sets returns a observable of true.

I've tried adding a ChangeDetectorRef like

  // Get an observable of the login state
  public getAndSetLoginState() {
    this.userService.checkedLoggedInStatus().subscribe((loggedInState: any) => {
      this.loggedIn = loggedInState;
      this.cd.markForCheck();
      // cd = ChangeDetectorRef initliased in the constructor
    });
  }

But that doesn't detect my changes either.

Am I correct that Angular only loads the HTML once, because of that, ngIf statements only work if you change them onInit or in the constructor.

How can I show/hide content depending on the login state. I've heard about using RXJS BehaviourSubject but not sure how that would help.

4

4 Answers

2
votes

You can save loggedInState in your UserService file.

export class UserService{
    private logingData;
    private loggedIn = false;

  constructor(
    private http: HttpClient,
  ) { }

  login(){
    this.logingData= this.http.post(-call your server-);
    return this.logingData;
    this.loggedIn = this.logingData;
  }
}

Then bind that loggedIn varible to toolbar.

In html

<ion-buttons *ngIf="!userService.loggedIn" slot="end">

In ts

import { UserService} from "your location";

constructor(public userService: UserService){}

Then call this method from Popover component.

public getAndSetLoginState() {
   this.userService.checkedLoggedInStatus().subscribe((loggedInState: any) => {
       console.log(loggedInState);
   });
}

I hope this will help you.Thank you.

0
votes

You need to create an Observable for that. Create a UserService service class & create BehaviourSubject object in it. Set it's value on successful login.

Like this:

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

@Injectable({
    providedIn: 'root'
})
export class UserService {
    private isLoggedIn: BehaviorSubject<boolean>;
    constructor() {
        this.isLoggedIn = new BehaviorSubject<boolean>(false);
    }
    
    setUserLoggedInStatus(value) {
        this.isLoggedIn.next(value);
    }

    getUserLoggedInStatus(): Observable<any> {
        return this.isLoggedIn.asObservable();
    }
}

Now in your component class, subscribe getUserLoggedInStatus() function like this:

import { Component, OnInit } from '@angular/core';
import { UserService } from '@app/shared/services/user.service';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
  isLoggedIn: Boolean;
  constructor(private userService: UserService) { }

  ngOnInit() {
    this.userService.getUserLoggedInStatus().subscribe((status)==> {
        this.isLoggedIn = status;
    });
  }
}
0
votes

Use BehaviourSubject in this kind of situation.

Service File:

import { Observable, BehaviorSubject } from 'rxjs';
 export class UserService {
   private isLoggedIn: BehaviorSubject<boolean>(false);
   private _isLoggedIn$ = new BehaviorSubject<boolean>(false);
   readonly isLoggedIn$ = this._isLoggedIn$.asObservable();
     
   getLoggedInStatus(): Observable<any> {
       return this.http.get<any>(url, params).pipe(
          map((res) => {
            this._isLoggedIn$.next(res);
             ..... // other logics here
       })
     );
    }
  }

Component:

loggedInState$:Observable<any>;
this.loggedInState$ = this.userService.isLoggedIn$();

HTML: (Use async pipe)

<ion-buttons *ngIf="!loggedInState | async" slot="end">
0
votes

S Rana's answer almost works, I'm posting the changes to get it working

Service File:

import { Observable, BehaviorSubject } from 'rxjs';
        export class UserService {
          private isLoggedIn: BehaviorSubject<boolean>(false);
          private _isLoggedIn$ = new BehaviorSubject<boolean>(false);
          isLoggedIn$ = this._isLoggedIn$.asObservable();
            
          getLoggedInStatus(): Observable<any> {
              return this.http.get<any>(url, params).pipe(
                 map((res) => {
                   this._isLoggedIn$.next(res);
                    ..... // other logics here
              })
            );
           }
         }

Component:

loggedInState$:Observable<boolean>;

this.userService.loggedInChanged$.subscribe((data: any) => {
  this.loggedInState$ = data;
  }
);

HTML:

<ion-buttons *ngIf="!loggedInState$" slot="end">