5

Goodday, This is probably a nooby question but I can't get it to work.

I have a simple service which toggles an boolean, if the boolean is true the class active should appear on my div and if false no class.. Simple as that. But the boolean gets updated, but my view doesn't react to it. Do I somehow have to notify my view that something has changed ?

Service:

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

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

    public menuActive = false;

    toggleMenu() {
      this.menuActive = !this.menuActive;
    }
}

View (left menu component):

 <div id="mainContainerRightTop" [class.active]="classToggleService.menuActive == true">

Toggle point (top menu component):

<a id="hamburgerIcon" (click)="classToggleService.toggleMenu()">
2
  • 1
    try simply by "[class.active]="classToggleService.menuActive" Commented Nov 22, 2018 at 7:45
  • 1
    I tried this, but this didn't work so as a test i wrote it out fully by using == true Commented Nov 22, 2018 at 7:58

2 Answers 2

3

This because you are changing a value on a service not on the component, so Angular don't need to update the component, because it did not change. If you want to update the view of your component when a service element is modified, you have to use an Observables and Subjects, and subscribe to them. In this way when the element is changed, it automatically notify all the subscribed components.

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

    public menuSubject: Subject<boolean> = new BehaviorSubject<boolean>(false);
    public menuActive = this.menuSubject.asObservable();
    toggleMenu(val : boolean) {
      this.menuSubject.next(val);
    }
}

And in your component just implement OnInit interface and subcribe to the observable in the your service:

public localBool = false;
ngOnInit() {
   this._myService.menuActive.subscribe(value => this.localBool = value);
}
ComponentToggleMenu() {
   this._myService.toggleMenu(!this.localBool);
}

Then your html:

    <div id="mainContainerRightTop" [class.active]="localBool">
   <a id="hamburgerIcon" (click)="ComponentToggleMenu()">
Sign up to request clarification or add additional context in comments.

6 Comments

You have to DI your service in your component constructor: constructor(private _myService: ClassToggleService) {}
Thanks this works, was thinking about a solution like this, just wasn't sure how to implement it. One problem though. The value always stays false and doesn't toggle. Any idea on how to fix that part ?
Thanks thats better, I stored the variable in my service instead of my component so my subscribtion now toggles true/false, I put that in localBool and use that for class.active. But somehow my view doesn't update.. that quite weird cuz when i console log in my subscribe it sends the right values... Any idea?
Even if I just use an public variable in my component, and toggle it in the same component the view doesn't update. The bool gets updated, if I debug or console the value toggles betweet true and false so that alright. But the class does not get added.
Alright thanks it works now, apparantly i had to run ng serve again... idk why. But it works. Thanks for your effort, marked your comment as answer.
|
1

Why we need service, this should be integrated with component class. As a general rule, you are not supposed to call service method in template file.

export class TestComponent implements OnInit{
   public menuActive = false;

    toggleMenu() {
      this.menuActive = !this.menuActive;
    }
}

Template:

<div id="mainContainerRightTop" [class.active]="menuActive">

9 Comments

So where It is stated in your answer that why it is not working with service?
Using Service is not a prefered appraoch. You are not allowed to bind service class in template
Can you redirect me using link where it is written that Using Service is not a prefered appraoch? and why I am not allowed to bind service class in template?
It's quite simple. Any component can inject the service and modify public variables. If it is inside component. only that component and child components can update it.
I can't do it in the same component because the toggle part is in another component then the menu itself. I am aware that getting the menuActive directly from the service in the view is not best practice, but I don't see a problem in using an service in general and not calling it directly from the view.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.