Obtaining the initial value from an Observable in Angular 8+

Initially, I have a page form with preset values and buttons for navigating to the next or previous items.

Upon initialization in ngOnInit, an observable provides me with a list of 3 items as the starting value - sometimes it may even contain 4 items.

However, before proceeding to the next page, it is crucial that I click on a button triggering the function calculate(). This function makes a request which updates the observable List to include 4 items.

When I click on the next button onNextButton(), I wish to compare the initial value with the current one to determine if any changes have occurred. Unfortunately, my current implementation doesn't store the initial value properly, resulting in issues when comparing values upon clicking the next button.

This is my code:

export class PageComponent implements OnInit {

   questions$: Observable<any[]>;
   hasChange: boolean;

   ngOnInit() {
     // GETTING INITIAL VALUE
     this.questions$.subscribe((quest: any[]) => {
        this.hasChange = quest.length > 3 ? true : false
     });
   }

   calculate() {
      // make a request
      // the observable will now contain 4 items.
   }

   onNextButton() {
      if (hasChange) {
         // submit()
      } else {
         // navigate()
      }
   }
}

Therefore, I am looking for a way to retain the previous value of the Observable and store it in a variable, or alternatively, how to detect any changes effectively.

I have attempted using `behavioursubject` and `pairwise` from RxJS, but I am uncertain about their correct usage in my case.

Thank you in advance for your help!

Answer №1

To maintain the last emitted value, you'll need to use either ReplaySubject or BehaviourSubject because Observable doesn't have that capability. ReplaySubject and BehaviourSubject function similarly, both sending the last emitted value upon subscription. However, ReplaySubject only emits the last value at subscription while BehaviourSubject stores a list of previous values (with a configurable size). I prefer using BehaviourSubject as it offers more features.

Simply replace your Observable with BehaviourSubject, remembering to specify the memory size when creating an instance. For example, you can create a method returning a BehaviourSubject with the last boolean stored like this:

private fooBehaviourSubject;

ngOnInit(): void {
    this.fooBehaviourSubject = new BehaviorSubject<boolean>(1); // 1 represents the stack size
    this.fooBehaviourSubject.next(true); // <- Initial value emitted here
}

getValue(): BehaviourSubject<boolean> {
    return this.fooBehaviourSubject;
}

When subscribing like this:

getValue().subscribe(e => console.log(e))

The last stored value (true) will automatically be retrieved and displayed in the console. Just make sure you've emitted at least one value beforehand, as the subscription won't execute until then. Any updates to the value will trigger the console log with the new value.


Incorporate this into your code by creating the BehaviourSubject in ngOnInit, subscribing to it within ngOnInit to define the callback event, and calling the next method on BehaviourSubject when updating the list.

Answer №2

class PageComponent {
    questions$: Observable<any[]>
    hasChange: boolean

    constructor() {}

    ngOnInit() {
        let hasSome = false

        this.questions$
            .subscribe((quest: any[]) => {
               hasSome = quest.some(item => item.id === 'whatever')
        )

        this.hasChange = hasSome
    }

    calculate() {
        // make a request here to update the observable with 4 items.
    }

    onNextButton() {
        if (this.hasChange) {
            // call submit function
        } else {
            // navigate to another page
        }
    }
}

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

Leveraging the keyword 'this' within an object method in node's module.exports

My custom module: module.exports = { name: '', email: '', id: '', provider: '', logged_in: false, checkIfLoggedIn: function(req, res, next){ console.log(this); } }; I inclu ...

Uploading photos to Postgres through express/multer

Currently, I am using Postman to send images to a POST route through the Express library. However, when I retrieve the buffer of binary data, I am unable to process it accordingly. Will using body-parser resolve this issue? This is how I am uploading the ...

Increasing Taxes and Boosting the Overall Cost

How can we set up a system where taxes are bypassed by default unless otherwise specified when placing an order? Let's take a look at the following text box: <input class="txt1" type="text" name="subtotal" value="" id="subtotal" size="16" ta ...

Angular: Intercepting an HttpResponse to trigger additional calls before passing the response back to the caller

My current objective is to intercept a response and, if a certain value (CHALLENGE) is present, trigger a call to another API. I need to retry this process 3 times if necessary. Upon success, I should respond to the initial call and pass the result back to ...

Guide to fetching and returning data from AJAX using a function

In my JavaScript file, I have a function that retrieves a value asynchronously from the server: function retrieveValue(userId) { $.ajax({ type: "POST", url: "http://localhost/bghitn/web/app_dev.php/get_number_of_articles", data ...

The art of integrating partial rendering into a template

I'm currently working on a project using Angular 2 and I need to display a partial inside a template without having to create a new component. Is this doable? import {Component} from 'angular2/core'; import {RouteConfig, ROUTER_DIRECTIVES} ...

WebGL annotations failing to display on the webpage

I'm currently working on displaying a 3D model using Three.js in a web browser and looking to incorporate annotations like the ones shown in this Sketchfab model: Interactive 3D Test. I came across a helpful guide at this link, but I'm facing iss ...

Guide to importing external CSS styles into Angular 2 using the require method

I'm facing an issue with loading an external css file in different environment files. My setup includes two environments: development and production. Loading the css file locally works fine in development mode, but not in production mode. environment ...

Problem with laravel ajax request

I've spent the entire weekend trying to figure this out, but I can't seem to make it work. It works fine with the 'get' method, but not with 'post'. I'm using Laravel 4 and jQuery. Here's how my JavaScript looks: $ ...

Exploring ways to retrieve a video thumbnail with VueJS3

I am currently working on a project to create a simple program that retrieves movies from my AWS-S3 bucket and transforms them into picture thumbnails. Below is the code I have written: <template> <img :src="imgURL" class="card- ...

Encountering an error while attempting to add class-constructed objects to an array list in React/NextJs: "Unable to add property 0, as the object is

This function contains the code required to generate rows for display in a Material Ui table. class User { constructor(id, name, email, measured, offset, paidAmount, status, home, misc, plane, transport, partner, isCoupon) { thi ...

Guide on redirecting to a new domain using a cookie in Express.js

I am working on a web app using Express on Node and I want to add a proxy login feature that allows users to be automatically logged in and redirected to another site after logging into my site. Within my routing function, I have the following code: res ...

Is it feasible to cancel or clear the queue for a jQuery fadeOut function after a delay is specified? If so,

Can anyone help me out with this question? Is there a way to eliminate the delay in chaining? Mn.Base.TopBox.show = function(timedur){ $('#element').fadeIn().delay(timedur).fadeOut(); } Mn.Base.TopBox.cancelFadeout = function(){ } I&apos ...

How to prevent the 'page' output event from triggering when scrolling in ngx-datatable?

My preference is to avoid infinite scroll pagination; instead, I only want pagination to be triggered by clicking the page numbers in the footer. Since I am using server-side pagination, constantly triggering the 'page' event with every scroll ca ...

Unable to retrieve information from the JSON file

I'm having trouble retrieving data from a JSON file in my script: <script type="text/javascript" src="jquery-1.7.min.js"></script> <script type="text/javascript"> $(document).ready(function () { $('#useruname').ch ...

The pause button will still function, even if the scrolling feature is enabled

I've successfully implemented a feature that pauses and plays the video on scroll when it reaches a certain pixel height. However, I'm facing an issue where the code automatically plays the video whenever the scroll position is more than 13500px ...

The React component does not trigger a re-render

Using React Redux, I am able to pass values successfully. However, the component I intend to render only does so once. Interestingly, when I save my code in VSCode, it renders again and the data displays on the page as expected. return ( <div classN ...

Implementing Angular with HTML progress bar for interactive client-side features

Exploring the integration of HTML built-in progress bars with Angular: <label for="file">File progress:</label> <progress id="file" max="100" value="70">30%</progress> I am curious about how ...

Tips for invoking a JavaScript function within an iframe

I'm looking to add an iframe to my HTML document, but I also need to pass a variable from a JavaScript function that is located on the same page (which retrieves cookie values). <script type=text/JavaScript> var generateLinkerUrl = function(url ...

The modal window obstructs my view on the screen

You are working with a modal form that triggers a POST method in your controller Here is the view code: <div class="modal fade" id="agregarProducto"> <div class="modal-dialog" role="document"> <div class="modal-content"> ...