Implementing Angular: Updating values in separate components using a boolean value and a shared service

Recently delving into Angular and facing a particular challenge: I have created two components, namely header and main. The header contains a toggle button while the main houses the sidenav. My goal is to make the button in the header hide and show the sidenav in the main component upon clicking it. After trying various approaches, it became apparent that using services was necessary due to the components not being directly related as child and parent.

(Toggle.service.ts)

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

@Injectable({
      providedIn: 'root'
    })
    export class ToggleService {
    
        choice = true;
    
        toggle() {
          this.choice = !this.choice;
        }
    }

(Header.component.ts)

import { Component, OnInit } from '@angular/core';
import { ToggleService } from '../../services/toggle.service';


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

  constructor(private myservice: ToggleService) { 
    
  }
  ComponentToggleMenu() {
    this.myservice.toggle();
 }
  ngOnInit(): void {
  }

(Header.component.html)

<button (click)="ComponentToggleMenu()"><i class="material-icons">menu</i></button>

(Main.component.ts)

import { Component, OnInit } from '@angular/core';
import { ToggleService } from '../../services/toggle.service';

@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.css'],
})
export class MainComponent implements OnInit {
  boolean = this.myservice.choice;


  constructor(private myservice: ToggleService) {}

  ngOnInit(): void {

  }

}

(Main.component.html)

<mat-sidenav class="sidenav" mode="side" [opened]="boolean">

Despite my efforts, I haven't been able to get it working perfectly. Deployed the app on Github where you can see the issue for yourself. One important note is that the communication between components seems more complex than anticipated, making it difficult to implement changes smoothly across different components. If you face similar challenges, feel free to check out the repository and deployed version below:

(updated) I didn't fix it, but I made the deploy of the app in the Github and here is the link of the depository and deploy.One detail it's in Portuguese but just click in the toggle button, there is 2 buttons toggle, one in the main component that it's working and the another one in the header component that it's not working. Depository - https://github.com/EltonModellingDesign/Client-Registration-Angular-app Deploy -

Answer №1

The issue lies in the fact that you are assigning boolean = this.myservice.choice, which is a primitive value, not an object reference. Consequently, boolean will not be updated when this.myservice.choice changes.

Instead, it would be better to directly bind the opened property of your mat-sidenav component to myservice.choice. Additionally, ensure that myservice is declared as public so that it can be accessed from your template.

<mat-sidenav class="sidenav" mode="side" [opened]="myservice.choice">

You can refer to this StackBlitz example for a similar implementation with these adjustments applied.

Answer №2

boolean within the MainComponent will not be updated as this.myservice.choice is not a reference.

You can directly access the service value from your template.

<mat-sidenav class="sidenav" mode="side" [opened]="myservice.choice">

Additionally, you need to change myservice visibility from private to public for referencing from the template.

constructor(public myservice: ToggleService) {}

UPDATE If you wish to update the value in MainComponent for any reason, you can follow this approach.

toggle.service.ts

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

@Injectable({
  providedIn: 'root'
})
export class ToggleService {
    
  choice$ = new BehaviorSubject<boolean>(true);  
    
  toggle() {
    this.choice$.next(!this.choice$.value);
  }
}

main.component.ts

import { Component, OnInit } from '@angular/core';
import { ToggleService } from '../../services/toggle.service';

@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.css'],
})
export class MainComponent implements OnInit {
  boolean = true

  constructor(private myservice: ToggleService) {}

  ngOnInit(): void {
    this.myservice.choice$.subscribe( choice => {
      this.boolean = choice;
    })
  }

}

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 is the proper way to utilize ngIfElse in Angular 9?

Currently, I have a list of posts that are being fetched using services and displayed on the UI. There is a search box with an ID field specified in it. My goal is to render the post in a card if the provided ID exists. This functionality is working well. ...

Under what circumstances would you need to manually specify the displayName of a React component?

After coming across an article (linked here: https://medium.com/@stevemao/do-not-use-anonymous-functions-to-construct-react-functional-components-c5408ec8f4c7) discussing the drawbacks of creating React components with arrow functions, particularly regardi ...

The Typescript object property is deemed as 'undefined' even though it has not been defined

I'm relatively new to working with Typescript and I'm facing a challenge that seems quite silly: When I fetch an 'agent' object from a service. this.agentsController.getAgent(matricule).subscribe({ next: agent => { con ...

Is it necessary to include a module in another module if it is not utilized in the template?

Is it necessary to import Module2 into Module1 if a component from Module2 is being used in Module1, but only in the typescript and not the template? For instance, as a @ContentChild(Component2) component2 like shown below (Note: both modules are secondary ...

Tips for creating unit tests for my Angular service that utilizes the mergeMap() function?

As a beginner with the karma/jasmine framework, I am currently exploring how to add a test case for my service method shown below: public getAllChassis(): Observable<Chassis[]> { return this.http.get('chassis').pipe( merge ...

Instant reaction upon subscription

Presenting my unique service: @Injectable({ providedIn: 'root' }) export class DataService { @Output() data: EventEmitter<number> = new EventEmitter(); constructor() { setInterval(() => { this.data.emit(Math.random()); ...

How can we efficiently determine if a background image is broken in Angular 5 and substitute it with a default image?

When working with Angular 2+, we often use the <img> tag to display images using a syntax like <img [src]="myDp" (error)="myDp='assets/media/user/default_dp.jpg'">, where myDp contains the relative path to the image on the server. Is ...

Angular 10's tree shaking feature successfully eliminated the AsyncPipe module when setting sideEffects to false

Angular 10's tree shaking feature is causing unexpected issues with my AsyncPipe. A recent blog post on Angular 10's release notes introduces a new --strict mode for ng new: One interesting point it raises is: Setting up your app as side-effe ...

Exploring data in Angular 8 and Firebase following the addition of a new item

Currently in my possession: Two Models: User.ts and Company.ts I aim to have each User linked to only one company, so that when a user registers, a new company is automatically registered on the firestore table. The following diagram provides a clear ...

When utilizing AngularFire with Firebase Firestore Database, users may encounter instances where data duplication occurs on

Currently facing a challenge in my Angular 13.1 Project utilizing @angular/fire 7.4.1 for database management The issue arises consistently across various screens where data from Firestore Database is displayed, particularly on List screens. The lists are ...

It seems that change detection is triggered by a click event regardless of the detachment setting

My understanding of Angular 2 change detection may be off, but I expected that if a component's ChangeDetectionStrategy was set to Checked, CheckOnce or Detached, the component would only check for changes once upon instantiation. However, it seems to ...

"An error in the signature index results in the failure of the

I'm encountering a coding issue that's puzzling me. The TypeScript index signature I included in my code is as follows: const ships: { [index: string]: Ship } = {}; This snippet of code contains the problematic line: recieveAttack(e: any) { ...

What could be causing this function to malfunction?

Apologies for any inaccuracies in technical terms used here. Despite being proficient in English, I learned programming in my native language. I am currently working on a project using the latest version of Angular along with Bootstrap. I'm unsure if ...

What is the reason for Angular 2 opting for an Observable<boolean> as the return type for CanActivate rather than using a Promise?

The CanActivate class allows for a return type of Observable<boolean>. I can think of two potential use cases: CanActivate could delay the display of a route until observer.next(true|false) is called. Displaying a route permitted by CanActivate, t ...

How can we send a parameter to a subscribe function for retrieving the contents of an assets file in TypeScript and Ionic 3?

When working in TypeScript, I have discovered a way to retrieve the content of a text file from my assets directory using the following code: this.http.get('assets/data/file_1.txt') .subscribe(data=>{ let obj = data['_body']; ...

Is it possible to remove the top route in Angular 7 Router?

In my application, I have a bootstrap-modal that I want to sync with the browsing history. This means that when the modal is open and the user clicks the browser's back button, I want the modal to close. I am well-versed in Angular's Location ob ...

Losing the generic type in nested interfaces

Having issues with generics and 'nested' interfaces when working with ReadonlyArray. Is there a way to utilize the filterList function without losing the type for the list parameter? interface INumber { value: number } interface IState { ...

The Angular frontend implemented with Nginx fails to establish a connection with the Django Rest Framework (DR

I've set up a drf backend and angular frontend on the same aws instance, utilizing Nginx and gunicorn for the drf, and Nginx for the angular. While the drf API tested fine using Postman, the angular frontend is unable to connect to the API. The site l ...

Leverage Formidable to directly stream content to Azure Blob Storage without the need to save it in the /tmp directory

An interesting example provided by Formidable can be found here: https://github.com/node-formidable/formidable/blob/master/examples/store-files-on-s3.js. It showcases how to upload a stream to an S3 bucket without saving the content to a temporary file, wh ...

Utilizing a singleton service within a form validation function

My current form validator function is quite simple. static required(control: FormControl) { if (control.value == null || control.value.length <= 0) return {'required': false, 'errorMsg': 'Value is required'} re ...