Trigger a dialog box upon page transition through menu navigation in Angular 4

I need assistance with my Angular 4 application. I am trying to implement a dialog box on the editionPage that prompts users to confirm before leaving the page.

Currently, I have a button that opens the dialog when clicked to go back to the previous page. However, I also want to trigger the dialog when clicking on a button from the sidebar menu.

This is an example of my sidebar menu:

<nav class="sidebar" [ngClass]="{sidebarPushRight: isActive}">
<ul class="list-group">
    <a routerLink="/first" [routerLinkActive]="['router-link-active']" class="list-group-item">
        <div class="titleMenu first" >{{ 'first' | translate }}</div>
    </a>
    <a routerLink="/tests" [routerLinkActive]="['router-link-active']" class="list-group-item">
        <div class="titleMenu">{{ 'Tests' | translate }}</div>
    </a>
</ul>
</nav>

To open the modal dialog, I use the following code:

this.bsModalRef = this.modalService.show(DialogSaveEditComponent);

I initially tried using a guard with CanDeactivate, but it did not work as expected because the page would change before the user could choose an option in the dialog.

If you have any suggestions on how I can resolve this issue, please let me know.

EDIT I have updated my approach by calling a function to open the dialog when a button from the menu is clicked. However, due to

routerLink="/first" [routerLinkActive]="['router-link-active']"
, the page changes before the dialog appears. Is there a way to delay the page change until after the dialog option is selected or cancel the page change altogether?

Answer №1

If you want to trigger a modal at the end of navigation, you can achieve this by utilizing the following code snippet:

this.router.events.subscribe(
        event => {
            if(event instanceof NavigationEnd && event.url.startsWith('YOUR URL')) {
               //DISPLAY YOUR MODAL HERE
            } 
        }
    )

Answer №2

I found success in achieving my goal by implementing a guard to prevent users from changing pages.

Below is the implementation of the new guard:

@Injectable()
export class SaveEditGuard implements CanDeactivate<ConfirmDialogSaveBatch> {
    sub: Subscription;
    result: boolean;

constructor(private router: Router, private confirmDialogService: ConfirmDialogSaveBatchService, private datasService: DatasService) {

}

canDeactivate(component: ConfirmDialogSaveBatch, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot,
              nextState?: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {

    if(!this.datasService.clickOnSaveButton){
        this.confirmDialogService.confirm();
    }

    return this.datasService.returnSaveEditValue$;
}
}

When a user clicks on the save button, I ensure that the dialog is not displayed. By setting

this.datasService.clickOnSaveButton
and returnSaveEditValue to true upon clicking the save button, we allow the user to exit the page seamlessly.

If the user attempts to leave the page through the menu, the dialog opens and awaits a response due to a ReplaySubject<boolean>.

The following code is implemented in the service:

public returnSaveEditValue = new ReplaySubject<boolean>(1);
public clickOnSaveButton: boolean = false;


public notifyRefreshDatas(data: any) {
    if (data) {
        this.subject.next(data);
    }
}

setReturnSaveEditValue(val: boolean){
    this.returnSaveEditValue.next(val);
}

get returnSaveEditValue$() {
    return this.returnSaveEditValue.asObservable();
}

Upon a user clicking on save, the observable variable is set to true using the function:

this.datasService.setReturnSaveEditValue(true);
. To handle subsequent interactions where the user may want to quit the page or display a new dialog, the ReplaySubject is reinitialized with:
this.datasService.returnSaveEditValue = new ReplaySubject<boolean>(1);
. This ensures that if the user cancels an action and tries to leave the page again, the app waits for a response from the dialog.

To enable calling the dialog from anywhere, a dedicated dialog service was created. Within this service, there is a function responsible for invoking and opening the dialog.

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

What is the best way to utilize @Input in components that have been generated using ComponentFactoryResolver?

Is there a way to specify an @Input property for an Angular 2 component that is created dynamically? I am utilizing the ComponentFactoryResolver to generate components within a container component. For instance: let componentFactory = this.componentFacto ...

Issue encountered in Angular-CLI when running the command "ng e2e": inability to access localStorage in protractor tests due to ts-node limitations

In my Angular2 project, I am using ngrx and the @angular/cli: 1.0.0-beta.32.3 version. The structure of my app is very similar to the ngrx example app found at https://github.com/ngrx/example-app. I have integrated localStorage synchronization using the h ...

Error message alert - Subscription unable to capture observation

Currently, I am utilizing RXJS observable within Angular 4 in my project. import { Observable } from 'rxjs/Observable'; import 'rxjs/add/observable/from'; The function that I have created looks like this: public temp(){ retu ...

Uncertain of the cause for the Angular error; baffled by its

I am new to JavaScript and Angular 2 Whenever I try to move the three dots in the grid, I encounter the following error. Can someone guide me on how to resolve it? The complete code is provided in the fiddle along with relevant snippet ...

Encountering a Typescript error while attempting to remove an event that has a FormEvent type

Struggling to remove an event listener in Typescript due to a mismatch between the expected type EventListenerOrEventListenerObject and the actual type of FormEvent: private saveHighScore (event: React.FormEvent<HTMLInputElement>) { This is how I t ...

Sorting elements with a custom selector using Angular's ViewChild

Currently, I am delving into the realm of angular ViewChild. However, I find myself facing a roadblock when attempting to utilize ViewChild in selecting custom reference variables from the DOM. Within my template lie two tables: <mat-table #eventTable ...

What is the best way to reassign key-value pairs in JSON mapping using JavaScript/TypeScript?

Given {"a": {"name": "king", "firstname": "Thomas"},"b": {"age": "21"}} I'm exploring a simple way to convert it to {"name": "king","firstname": "Thomas","age": "21"} In the realm of Javascript/Angular. Any helpful suggestions are greatly appreci ...

Identifying the web browser by utilizing the UserAgent detection method

How can I determine if the current browser is Chrome using TypeScript/JavaScript? I previously used the following method: var isChrome = !!(<any>window).chrome && !!(<any>window).chrome.webstore; However, this doesn't work anymo ...

Scheduling emails using Node JS

I am currently developing a web application using Angular for the frontend and NodeJS for the APIs. I have a requirement to schedule emails on specific dates without relying on external calls. After researching, I found the node-schedule library. My ques ...

Tips for extracting a specific key value from JSON data, eliminating duplicates, and adding them to an array in Angular 6 without using a for loop

Here is an example of JSON data: data = [ { position: 'Active', name: 'name1', email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3e535f57520f7e535f5752105d5153">[email protected]< ...

The parameter type 'string | null' cannot be assigned to the value function 'ValueFn<SVGPathElement, Datum[], string | number | boolean | null>'

I recently delved into the world of d3 and attempted to create a simple line chart using d3, TypeScript, and react. However, I keep encountering a TypeScript error whenever I try to implement it. Strangely, I can briefly see my chart before it disappears a ...

What's the process for validating i18n dictionaries using TypeScript?

Is there a way to enforce type checking on existing keys within dictionaries in react-i18next? This means that TypeScript will provide warnings at compile time if a key does not exist. For example: Let's say we have the following dictionary: { "f ...

Enhance your React application by using a personalized hook that allows you to trigger a function

After creating a custom hook to handle uploads to an AWS S3 bucket, I encountered a small issue. Rather than having the hook execute the logic directly, I decided to create an executable function to return instead. However, I am facing a problem where the ...

Optimal approach to configuring Spring Boot and Angular for seamless communication with Facebook Marketing API

Currently, I am working on a Spring Boot backend application and incorporating the Facebook marketing SDK. For the frontend, I am utilizing Angular 10. Whenever I create a new page or campaign, my goal is to send the corresponding object back to the fronte ...

Tips for utilizing the keyword 'this' within a Promise

Seeking assistance with resolving an issue involving an undefined error when attempting to make an http request within a Promise function. The error occurs due to this.http.post being undefined, indicating that there is an issue with accessing this properl ...

Creating a data structure that consists of pairs of elements, inspired by the alignment of domino bricks, using TypeScript syntax

My goal is to establish a type alias in TypeScript that allows all values which are arrays of Domino pairs, where each pair connects like domino bricks: Pair<A,B> connects with Pair<C,D> only if B = C. For example: const chain1: DominoChain = ...

Error in Node.js with MongoDB: Array of OptionalId<Document> Typescript typings

I have successfully established a connection and written to my MongoDB collection, but I am encountering a type error that is causing some confusion. Below is the code snippet along with the error message: interface Movie { id: number; title: string; ...

What is the best way to set up a variable in Typescript that will be assigned the value of an asynchronous request once it is completed?

As a newcomer to typescript, I encountered an issue that hadn't occurred in my previous project. It appears that declaring a variable before an API request inside a try-catch block leads to typescript errors when attempting to use this variable after ...

Tips for creating a seamless merge from background color to a pristine white hue

Seeking a seamless transition from the background color to white at the top and bottom of the box, similar to the example screenshot. Current look: The top and bottom of the box are filled with the background color until the edge https://i.stack.imgur.com ...

Can you explain the distinction between initially connecting the subject to the observable and doing so at the end, considering that they both operate asynchronously?

I recently encountered an interesting scenario involving code where I was attempting to connect a subject to an interval observable: const subject = new Subject(); // Establish the connection between the subject and the observable interval(1000).subsc ...