Change the variable value within the service simultaneously from various components

There is a service called DisplaysService that contains a variable called moneys. Whenever I make a purchase using the buy button on the buy component, I update the value of this variable in the service from the component. However, the updated value does not reflect in the sell component even though I retrieve the value from the service. The sell component displays the original value of the DisplaysService variable.

displays.service.ts

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

    @Injectable({
      providedIn: 'root'
    })
    export class DisplaysService {
      moneys = 50000;

      constructor() { }
    }

buy.component.ts


    import { DisplaysService } from './../displays.service';
    import { Component, OnInit } from '@angular/core';
    import { HttpClient } from '@angular/common/http';

    @Component({
      selector: 'app-buy',
      templateUrl: './buy.component.html',
      styleUrls: ['./buy.component.css']
    })
    export class BuyComponent implements OnInit {
      moneys : number;
      Response = {};
      selectedcurrency : string = "Select Currency"

      constructor(private http : HttpClient, private displaysservice : DisplaysService) { }

      ngOnInit(): void {
        this.http.get('https://api.coinranking.com/v1/public/coins?base=EUR&timePeriod=7d') 
        .subscribe(Response => { 
          console.log(Response)
          this.Response = Response 
        }); 
      }

      ChangeCurrencySymbol (newcurrency : string) { 
        this.selectedcurrency = newcurrency;
      }

      ChangeMoneys (moneysspent : Number) {
        this.moneys = this.displaysservice.moneys - Number(moneyssp$ent);
        this.displaysservice.moneys = this.moneys;
      }
    }

sell.component.ts


    import { DisplaysService } from './../displays.service';
    import { Component, OnInit } from '@angular/core';
    import { HttpClient } from '@angular/common/http';

    @Component({
      selector: 'app-sell',
      templateUrl: './sell.component.html',
      styleUrls: ['./sell.component.css']
    })
    export class SellComponent implements OnInit {
      moneys : number;
      Response = {};
      selectedcurrency : string = "Select Currency"

      constructor(private http : HttpClient, private displaysservice : DisplaysService) { }

      ngOnInit(): void {
        this.http.get('https://api.coinranking.com/v1/public/coins?base=EUR&timePeriod=7d') 
        .subscribe(Response => { 
          console.log(Response)
          this.Response = Response 
        }); 
      }

      ChangeCurrencySymbol (newcurrency : string) { 
        this.selectedcurrency = newcurrency;
      }

      ChangeMoneys (moneysspent : Number) {
        this.moneys = this.displaysservice.moneys + Number(moneysspent);
        this.displaysservice.moneys = this.moneys;
      }
    }

Link to stackblitz reproduction

Answer №1

The Challenge

Angular aims to enhance performance by updating the UI only when necessary.

Let's examine the following scenario:

  • You set the value of property DisplayService: moneys to $50,000.00
  • You assign the value of DisplayService: moneys to BuyComponent: moneys, resulting in a value of $50,000 for BuyComponent: moneys
  • You assign the value of DisplayService: moneys to SellComponent: moneys, resulting in the same value of $50,000 for SellComponent: moneys
  • Now, if we update SellComponent: moneys and then update DisplayService: moneys, there arises an issue as BuyComponent remains unaware of these changes

The Resolution

An effective solution is to use a BehaviorSubject to set the value of DisplayService: moneys and subscribe to it in both Buy and Sell components for synchronization. Here is a code snippet for reference:

displays.service.ts

  private readonly initialMoneys = 50000;
  moneysSubject$ = new BehaviorSubject(this.initialMoneys);
  moneys$ = this.moneysSubject$.asObservable();
  updateDisplay({ amount, type }) {
    if (type === "sell") {
      this.moneysSubject$.next(amount + this.moneys);
    }
    if (type === "buy") {
      this.moneysSubject$.next(-amount + this.moneys);
    }
  }
  get moneys() {
    return this.moneysSubject$.value;
  }

buy.component.ts

export class BuyComponent implements OnInit {
  moneys$ = this.displaysservice.moneys$;
  Response = {};
  selectedcurrency: string = "Select Currency";

  constructor(
    private http: HttpClient,
    private displaysservice: DisplaysService
  ) {}

  ngOnInit(): void {
    this.http
      .get("https://api.coinranking.com/v1/public/coins?base=EUR&timePeriod=7d")
      .subscribe(Response => {
        console.log(Response);
        this.Response = Response;
      });
  }

  ChangeCurrencySymbol(newcurrency: string) {
    this.selectedcurrency = newcurrency;
  }

  ChangeMoneys(moneysspent: number) {
    this.displaysservice.updateDisplay({ amount: moneysspent, type: "sell" });
  }
}

sell.component.ts

export class SellComponent implements OnInit {
  moneys$ = this.displaysservice.moneys$;
  Response = {};
  selectedcurrency: string = "Select Currency";

  constructor(
    private http: HttpClient,
    private displaysservice: DisplaysService
  ) {}

  ngOnInit(): void {
    this.http
      .get("https://api.coinranking.com/v1/public/coins?base=EUR&timePeriod=7d")
      .subscribe(Response => {
        console.log(Response);
        this.Response = Response;
      });
  }

  ChangeCurrencySymbol(newcurrency: string) {
    this.selectedcurrency = newcurrency;
  }

  ChangeMoneys(moneysspent: number) {
     this.displaysservice.updateDisplay({amount: moneysspent, type:'buy'});
  }
}

Check out the stackblitz demo here

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

Guide to adding a CSS class to an Ionic2 toast

i found a helpful resource on applying cssClass to my toast component. within my HTML, I have buttons: <button ion-button (click)="presentToast()"> toast</button> Here is the code snippet from my .ts file: presentToast() { let toast = t ...

"Error encountered while executing a code snippet using Navalia in TypeScript

I have been attempting to execute this code snippet from https://github.com/joelgriffith/navalia but despite my efforts, I have not been able to get it running smoothly without encountering errors: navaliatest.ts /// <reference path="typings.d.ts" /&g ...

Error in Angular 4: Unexpected 'undefined' provided instead of a stream

I encountered an issue while attempting to make a HTTP Post request. The error message I received is as follows: auth.service.ts?c694:156 Something went wrong requesting a new password, error message: You provided 'undefined' where a stream ...

Testing Vue components with Typescript and Jest does not display the expected values in the HTML output

Recently, I decided to focus on Test-Driven Development (TDD) using Typescript, so I started a new Vue project with vue-cli. I specifically chose Vue3, Typescript, and Jest for this project. However, when I ran the unit test initially, it failed to execute ...

Implementing Custom Font Awesome Icons in Your Angular Project

I recently upgraded to a fontawesome subscription with a paid plan and have successfully created some custom icons. Now, I'm looking to integrate these icons into my angular app. Here are the dependencies listed in my package.json file: "@fortawe ...

Utilizing TinyMCE with Angular 2: Customizing Editor Content with @Input Parameters

I am new to using Tinymce and I am unsure about where exactly I should place the setContent(this.content) method. The current setup I have is giving me an error: TypeError: null is not an object (evaluating 'body.nodeName') --- runTask — zone. ...

Is there a way to determine if a string is empty, even if it contains hard returns?

I am currently working on a function that checks if a string is empty or not, but it seems to be missing the detection of new lines. export const isStrEmpty = function(text: string): boolean { return !text || text.match(/^ *$/) !== null; }; I attempted ...

Tips for converting text input in a textbox to a Date value

My knowledge of Angular is limited, and we are currently using Angular 10. In our application, there is a textbox where users need to input a date in the format 10202020. This value should then be reformatted as 10/20/2020 and displayed back in the same ...

Listening for Internet Connection in Ionic and Angular

Currently, I am working on implementing a listener in my Ionic app that can detect changes in network activity and respond accordingly. import { Component } from '@angular/core'; import { Network } from '@capacitor/network'; @Component ...

What could be the reason for my function throwing a TypeError with the message "<function> is not a function"?

Every time I try to call a function that clearly appears to be defined as a function, I continuously receive the error message: TypeError: [function name] is not a function. To demonstrate the issue, here is a simple example: main.ts import someFunction ...

Property of object (TS) cannot be accessed

My question relates to a piece of TypeScript code Here is the code snippet: export function load_form_actions() { $('#step_2_form').on('ajax:before', function(data) { $('#step_2_submit_btn').hide(); $(&ap ...

I am experiencing an issue with my service provider when it comes to displaying multiple navigator stacks

Currently, I am developing a provider to manage the user's state across different views. The primary function of this provider is to display either one stack navigator or another based on whether a certain variable is filled or empty. This setup allow ...

TS2531: Nullability detected in object when using .match() method

I'm encountering a linting error on fileNameMatches[0] in the following code snippet. Strangely, the error doesn't appear on the Boolean() check. Even if I remove that check, the issue remains unresolved. Can anyone suggest a solution? protected ...

Steps for integrating the ts component into the index.html file

Is there a way to add the ts component in the index.html file? I've been looking for a solution for quite some time now, but haven't had any luck. Can anyone offer any suggestions or help? ...

Converting line breaks into a visible string format within Angular

After thorough research, all I've come across are solutions that demonstrate how to display the newline character as a new line. I specifically aim to exhibit the "\n" as a string within an Angular view. It appears that Angular disrega ...

Issue with maintaining variable state in Angular 7 service component

I currently have 2 components and a single service file in my Angular project, which consist of a login component and a dashboard component. The issue arises when I try to access the user data from the service file. In the login component, the user data i ...

Before running any unit tests, I have to address all linting issues as required by ng test

Upon running ng test, the output I receive is as follows: > ng test 24 12 2019 14:20:07.854:WARN [karma]: No captured browser, open http://localhost:9876/ 24 12 2019 14:20:07.860:INFO [karma-server]: Karma v4.4.1 server started at http://0.0.0.0:9876/ ...

Properties are determined by both the type and sub-type

A challenging TypeScript challenge. Exploring Multiple Discriminated Union Types This task involves intersecting multiple discriminated union types together, where there exists a relationship between "types" and their corresponding "sub-types." The Main Q ...

Deactivating a form field depending on a selected radio button in Angular 2

If I have two radio buttons, with a click function called localClick for the first button to give value 1 and the second button to give value 2. <div class="ui-g-12"><p-radioButton name="group1" value="Local" (click)=localClick(1) label="Local"&g ...

Why is it that TypeScript's flow analysis does not extend to the 'else' block?

Consider the code below: function f(x : number) { if (x === 1) { if (x === 2) {} // error } else { if (x === 1) {} // OK } } The compiler flags an error on x === 2. This is because if the code reaches this block, x must be ...