Angular: hiding a component with *ngIf doesn't work

Viewed 268

I have just started with Angular and have already faced an issue: a button actually toggles the variable I need (show) but it doesn't affect the course.component

course.component must show app-csgo-course, boolean show is true because the component is visible, but after it toggles in navbar.component, nothing changes.

<app-csgo-course *ngIf="show"> </app-csgo-course>

import { NavbarComponent } from './../navbar/navbar.component';
import { Component, OnInit} from '@angular/core';
import { CourseService } from 'src/app/course.service';


@Component({
  selector: 'app-course',
  templateUrl: './course.component.html',
  styleUrls: ['./course.component.css']
})
export class CourseComponent implements OnInit {

  constructor() { }

  ngOnInit(): void { }

  service = new CourseService;
  show = this.service.GetShow();
}

In navbar.component there's a button which toggles the "show" variable

      <button (click)="ToggleShow()" >
        <li class="nav-item active" id="csgo-logo">
          <a href="#">
            <img class="game-logo" src="assets\img\csgo-logo.png" title="Counter Strike: Global Offensive">
            <!-- <a>CS:GO <span class="sr-only">(current)</span></a> -->
          </a>
        </li>
      </button> 
import { CourseService } from 'src/app/cheat.service';
import { Component, OnInit, Input, Output, } from '@angular/core';

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

  service = new CourseService;
  show = this.service.GetShow();

  ngOnInit(): void {
    
  }

  public ToggleShow() {

    this.service.show = this.service.ToggleShow();
    console.log(this.service.show);
    return this.service.show;
  }
}

The course.service file


@Injectable({
  providedIn: 'root'
})
export class CourseService {

  show: boolean = true;

  GetShow() {
    return this.show;
  }

  ToggleShow() {
    return this.show = !this.show
  }

  constructor() { }
  }
}

Would appreciate your help!

1 Answers

Since you are new to Angular, let me break it down for you.

  1. You need to create a BehaviorSubject to capture the event of toggle (this is called reactive programming which is a achieved using RxJS in Angular ).

  2. Do not use new for a service, rather inject it in constructor.

course.service

@Injectable({
  providedIn: 'root'
})
export class CourseService {

  private show: boolean = true;
  private toggle$ = new BehaviorSubject<boolean>(true);

  constructor() { }

  toggleEvent() {
    return this.toggle$.asObservable();
  }

  toggleShow() {
    this.show = !this.show
    this.toggle$.next(this.show);
  }
}

in NavbarComponent

import { CourseService } from 'src/app/cheat.service';
import { Component, OnInit, Input, Output, } from '@angular/core';

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

  show = boolean;

  // IMP: make sure to inject the service and not do "new CourseService;"
  constructor(public service: CourseService){}

  ngOnInit(): void {
    this.service.toggleEvent().subscribe(showFlag => {
       this.show  = showFlag;
    })
  }

  public ToggleShow(): void {
    this.service.toggleShow();
  }
}

in courseComponent

import { Component, OnInit} from '@angular/core';
import { CourseService } from 'src/app/course.service';


@Component({
  selector: 'app-course',
  templateUrl: './course.component.html',
  styleUrls: ['./course.component.css']
})
export class CourseComponent implements OnInit {
 
 show: boolean ;
 // IMP: make sure to inject the service and not do "new CourseService;"
  constructor(public service: CourseService){}

  ngOnInit(): void {
    this.service.toggleEvent().subscribe(showFlag => {
       this.show  = showFlag;
    })
  }
  
}

PS: I would suggest you to read about "how to unsubscribe an observable" and how it causes memory leaks. Once you get some idea, you should implement that in the above provided code as well. That's a best practice. Happy learning. Let me know if you have any more questions

Related