Repeatedly calling the subscription results in the dialogue opening twice due to the state mutation with Ngrx in Angular

Repeated Dialog Opening Due to Multiple Subscription Calls in Response to ngrx State Mutation

  1. Attempted to use takeUntil(loadingComplete) where loadingComplete = new BehaviorSubject(false) but it did not work within the logic. This is because the subscription needs to be called at least once after the job state is "COMPLETED".

  2. Also tried using take(1) since I am polling to retrieve progress status, however, it cannot be fetched after the first subscription with take 1. Therefore, I added the isCompleteDialogOpened flag to control the multiple subscription dialog openings to happen only once. Despite setting the isCompleteDialogOpened flag to true after the first subscription in the openUploadCompleteDialog() method call, it remains false on the second subscription, causing multiple dialog openings.

    if(uploadStatus.jobStatus === 'COMPLETED' && !this.isCompleteDialogOpened)
    

Even after setting it to true on the first subscription in the openUploadCompleteDialog() method call, isCompleteDialogOpened is false on the second subscription, leading to multiple dialog openings.

 isCompleteDialogOpened = false;   // Initial as false

 ngOnInit() {
            this.pollUploadStatus(); // Call subscription method onInit
        }

 pollUploadStatus() { // Subscribed to uploadStore ngrx store when selectCurrentJob mutates
        this.uploadStore.select(selectCurrentJob)
            .pipe(filter(uploadJob => !!uploadJob && !!uploadJob.jobStatus))
            .subscribe((uploadJob) => { // Multiple subscription calls
                const uploadStatus = uploadJob.jobStatus;

                if (uploadStatus.jobStatus === 'COMPLETED' && !this.isCompleteDialogOpened) {
                    this.openUploadCompleteDialog(); // Dialog box called twice
                }             
    }


openUploadCompleteDialog(): void {

    this.isCompleteDialogOpened = true; // Set to true after dialog open on subscription

    const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
        data: ....
    });
    dialogRef.afterClosed().subscribe(result => {
        const message = this.translate
            .instant('upload-success');
        this.openUploadSnackBar(true, message);
        this.router.navigateByUrl('car/add-update/car-history');
    });
}

 ngOnDestroy() {
        this.uploadStore.dispatch(stopPolling({}));
        this.destroy$.next();
        this.destroy$.complete();
    }

May overlap with How to stop a subscription after the response to a service/store has a certain argument/value but takeUntil does not suit the logic in this case

Is there a way to ensure the dialog box opens only once after the state changes to "COMPLETED" based on a flag? If using a flag, how can the state be maintained on each subscribe? Any assistance is appreciated.

Using Angular8, Rxjs 6.5.2.

Answer №1

Not sure why the select function is triggering so frequently, but I have a solution:

 pollUploadStatus() { // --> uploadStore ngrx store when selectCurrentJob mutates this is subscribed
        this.uploadStore.select(selectCurrentJob)
            .pipe(filter(uploadJob => !!uploadJob && !!uploadJob.jobStatus))

Simply add distinctUntilChanged (possibly with a custom comparator for objects) to the pipeline after the filter function, and that should fix the issue.

Answer №2

After noticing that the subscription remained unsubscribed when navigating to another tab and returning, I utilized DistinctUntilChanged to debug and tidy up my code.

private destroy$ = new Subject<void>();

pollUploadStatus() {
    this.uploadStore.select(selectCurrentJob)
        .pipe(filter(uploadJob => !!uploadJob && !!uploadJob.jobStatus),
        distinctUntilChanged((prev, curr) =>
            prev.jobStatus.percentComplete === curr.jobStatus.percentComplete),
            takeUntil(this.destroy$))
        .subscribe((uploadJob) => {
            const uploadStatus = uploadJob.jobStatus;
            if (uploadStatus.jobStatus === 'COMPLETED') {
                this.openUploadCompleteDialog(); --> this.router.navigateByUrl('car/add-update/car-history');
            }
        });
}

ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
}

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

Using Typescript to create a Checkbox Grid that displays pipe-delimited values and implements a custom validation rule

I am currently working with a checkbox grid that contains pairs of AccountIds (consisting of x number of digits) and file names separated by a pipe delimiter. The file names are structured to always begin with either PRC or FE followed by a varying combin ...

Decoding the logic behind the *ngIf directive

Context In my code template, I am iterating over data retrieved from an HTTP response. <div *ngFor="let method of paymentMethods"> Within this loop, I am displaying method?.payment_profile_id Now, I want to display one of two elements based on ...

An issue occurred in React 16.14.0 where the error "ReferenceError: exports is not defined" was not properly

As the creator of the next-translate library, I have encountered a perplexing issue with an experimental version involving an error specifically related to React 16.14.0. Interestingly, upgrading React to version 17 resolves the issue, but I am hesitant to ...

The fuse-sidebar elements are not being properly highlighted by Introjs

I have recently developed an angular project that utilizes the fuse-sidebar component. Additionally, I am incorporating introjs into the project. While introjs is functioning properly, it does not highlight elements contained within the fuse-sidebar. The ...

Guide to implementing Google Adsense on a page post-load using Angular 6

Hi there, I recently completed my website www.revlproject.org and now I'm trying to get approved for Google Adsense. However, I keep receiving the message "valuable inventory: no content." After some investigation, I realized that because my site is b ...

Transferring Information Between Components

After logging into my login component, I want to pass data to my navbar component but unfortunately, my navbar content does not update. The navbar component is located in the app-module while the login component is in a separate module. I attempted to us ...

Customize the datepicker locale in Valor

Currently, I am working with Angular2 and typescript alongside the Valor datepicker. Unfortunately, the datepicker does not have the necessary locale built-in. After some research, I discovered that the essential JavaScript file containing the locale infor ...

Show the values in the second dropdown menu according to the selection made in the first dropdown menu using Angular 8

My goal is to retrieve data and populate two dropdowns based on user selection. However, the code I've written isn't giving me the desired output and instead, errors are occurring. Being new to Angular, I would appreciate a review of my code. Her ...

Having trouble getting the installed datejs typings to work properly

As I delve into Typescript due to my interest in Angular 2, I have come across the datejs Javascript library. To incorporate it into my Angular 2 project, I went ahead and installed datejs via npm, ensuring that it is correctly listed in my package.json. A ...

Steps for setting up a nested route in Angular 2

I am currently working on a project that includes an admin page (check the file structure below). I am trying to set up a child route named 'createuser' for the admin page (localhost:4200/admin/createuser). Despite my attempts, I encountered an e ...

Utilizing ngFor in Angular to dynamically refer to named variables within ngIf

I am looking to access the input element within the ngIf directive in order to check if it currently contains a specific value. The issue lies with the code inside the ngIf statement. <span *ngFor="let item of items;let i=index"> <input t ...

Vue's span function is yielding the promise object

In my Vue component, I am using the function getOrderCount to fetch the number of orders from a specific URL and display it in one of the table columns. <div v-html="getOrderCount(user.orders_url)"></div> async getOrderCount(link) { ...

Troubleshooting issue with Vue3 - TS Custom State Management

Issue: I am facing a challenge in transferring data between two separate components - the main component and another component. Despite attempting to implement reactive State Management based on Vue documentation, the object's value remains unchanged ...

A step-by-step guide on dynamically altering button colors in Angular 2

Struggling to dynamically change the color of my button, any suggestions? <a class="button buttonaquacss button-mini button-aqua text-right pull-right" (click)='send(button,detail.profile_id)' #button [ngStyle]="{'background-color' ...

Complete set of keys within a type

In my TypeScript project, I am working with an API (specifically OData API) to retrieve data. This API allows the selection of specific fields to retrieve. For example, api/some/getbyid(42)?$select=x,y,z can be used to get fields x, y, and z, along with s ...

Issue with Dynamic Theming in Ionic Framework

Currently, I am using Ionic in combination with Angular to create an App. I have introduced dynamic theming by adding two .scss files into my theme folder. In my app.scss file, I define the layout of components without colors, while all color styles are st ...

NEXT JS 13 experiencing an infinite loop when using State, encountering an error with Params, and facing issues with hook definition

Currently, I am in the process of developing a shopping cart using NEXT JS and encountering several issues within my code. To begin with, I have established a route [product]/[productitems] within the apps folder. In the page.tsx file of [productitems], I ...

ngFor is failing to show the array data, which is being fetched from Firebase

Hi there, I understand that this question has been asked frequently, but the regular solutions are not working for me. ts handleChangeFormType(formType) { this.serverData.getData('questionnaire/' + formType) .subscribe( (response: Respons ...

What category does a Fresh of Deno event fall under?

I'm currently working with Deno and fresh. When it comes to events in islands, what is the type for an event like the one below? export function Sample() { return ( <input type="file" onChange={(e) => ...} // What typ ...

The air-datepicker functionality seems to be malfunctioning within an Angular 4 environment

When using static HTML, it's quite simple to integrate Air Datepicker by following the documentation available at : <html> <head> <link href="dist/css/datepicker.min.css" rel="stylesheet" type="text/css"> <scr ...