0

I am calling this modal.service.ts from a component

export class ModalService {
  serviceText: boolean = true;

  toggleServices() {
    this.serviceText = !this.serviceText;
    console.log('test', this.serviceText);
  }
}

It is injected into options.component.ts below...

import { Component, OnInit, Input } from '@angular/core';
import { ModalService } from '../modal.service';

@Component({
  selector: 'app-options',
  templateUrl: './options.component.html',
  styleUrls: ['./options.component.css'],
  providers: [ModalService]
})
export class OptionsComponent implements OnInit {
  serviceText: boolean = false;
  constructor(private modalService: ModalService) { }

  ngOnInit() {
  }

  services() {
    this.modalService.toggleServices();
  }
}

The HTML for the options component is as follows, and has a click listener...

    <div class="tooth" >
      <img src="../../assets/tooth-brush.png" alt="tooth-brush" (click)='services()' style='cursor: pointer;'>
      <h5 (click)='services()' style='cursor: pointer;'>Services</h5>
      <app-services *ngIf="serviceText"></app-services>
    </div>

The services() in the options.component.ts is called, which in turn calls the toggleServices() in the modal.service.ts

The console does log 'test' and also True or False, which is the expected behavior.

BUT,

The <app-services *ngIf="serviceText"></app-services> in the options.component.html is not toggling between showing or hiding as I expected.

Can anybody see why this is not working?

Thanks in advance.

jesusWalks
  • 355
  • 4
  • 16
  • 1
    `serviceText` is defined in both the service and component, pick one or have the component point through back to the service either in the template or create a property. – Igor Dec 13 '19 at 14:00
  • Remember, having two fields named serviceText in two different classes is like having two guys named Steve, one in New York and one in Seattle. Just because New York Steve puts a quarter in his pocket doesn't mean that Seattle Steve now has it in his pocket. In fact, it means the opposite. – David Conrad Dec 13 '19 at 18:04

3 Answers3

1

You need to initialize serviceText in your component with this.modalService.serviceText which is something that you probably forgot doing.

Also, since this is a boolean in your service which you're updating which is primitive, it would be passed by value.

So you'll have to re-assing the serviceText in your Component with serviceText in your service every time you toggle serviceText on your service.

Do that in your Component like this:

import { Component, OnInit, Input } from '@angular/core';
import { ModalService } from '../modal.service';

@Component({
  selector: 'app-options',
  templateUrl: './options.component.html',
  styleUrls: ['./options.component.css'],
  providers: [ModalService]
})
export class OptionsComponent implements OnInit {
  serviceText: boolean = false;
  constructor(private modalService: ModalService) { }

  ngOnInit() {
    this.serviceText = this.modalService.serviceText;
  }

  services() {
    this.modalService.toggleServices();
    this.serviceText = this.modalService.serviceText;
  }
}

And this should all work as expected.


Here's a Sample Demo for your ref.

SiddAjmera
  • 38,129
  • 5
  • 72
  • 110
  • No, I just used this code in my project and it doesn't work. – jesusWalks Dec 13 '19 at 14:09
  • @JamesRossCodes Strange. I've attached a Sample Demo and I can see it working in there. ‍♂️ – SiddAjmera Dec 13 '19 at 14:11
  • Just to confirm - the only change I need to do are in the options.component,ts ? Ok, you're right, this is now showing the modal. Correct answer. – jesusWalks Dec 13 '19 at 14:13
  • Yes. That's correct. It's all there in the StackBlitz. If you click the `img` button, it will toggle the visibility of the `hello` Component. – SiddAjmera Dec 13 '19 at 14:14
  • I think that this approach isn't good enough to be accepted because toggleServices() method inside the ModalService can make some time to perform toggling (if it makes an async call or wait some time before toggling the state) so the serviceText inside the component could not reflect the real state inside the ModalService. – Bilel-Zheni Dec 13 '19 at 14:43
  • @Z.Bolbol, One shouldn't consider anything on their own unless it's specifically mentioned in the OP. Plus there are n different ways of achieving this by adding more and more complexity based on **n** different use cases. But I while answering would only accommodate the one that's specifically mentioned in the question. Also, I'm not gonna argue with you if you did this just for revenge – SiddAjmera Dec 13 '19 at 14:49
  • create an observable inside the service will be a better approach to keep the component informed of the latest state. – Bilel-Zheni Dec 13 '19 at 14:56
  • As I said, there are **n** different ways to do this. For simple use cases like these, `Observable` is an overkill. This is a simple solution that gets the job done. And I'm allowed to express my thoughts. You can suggest yours in your answer. That makes me wonder why you didn't suggest the approach that you're suggesting here, in your answer. – SiddAjmera Dec 13 '19 at 15:01
1

serviceText is defined in both the service and component, pick one or have the component point through back to the service either in the template or create a property.

export class OptionsComponent implements OnInit {

  get serviceText(): boolean { return this.modalService.serviceText; }

  /* rest of code unchanged... */
Igor
  • 60,821
  • 10
  • 100
  • 175
  • We should avoid setters and getters as much as possible. I've written an answer regarding the same [here](https://stackoverflow.com/a/59292529/2622292) which states the reason for it. – SiddAjmera Dec 13 '19 at 14:09
  • You might also want to check [this thread](https://twitter.com/SiddAjmera/status/1205321936584052736) out on Twitter for reasons. – SiddAjmera Dec 13 '19 at 14:10
-2

you need to use modalService.serviceText instead of serviceText because the ModaService is only updating its internal variable

ts

constructor(public modalService: ModalService) { }

html

<app-services *ngIf="modalService.serviceText"></app-services>
Bilel-Zheni
  • 1,202
  • 1
  • 6
  • 10
  • Services should ideally be kept `private`. Refer to [this answer by Deborah](https://stackoverflow.com/a/46596546/2622292) for more info. – SiddAjmera Dec 13 '19 at 14:05