Tips for Angular4: ensuring ngOnDestroy completion before navigation

My task involves managing a list of objects where the user can choose an object to edit using a child component. However, when the user returns to the list component, the child component needs to clean up in the ngOnDestroy method, which includes making a server call for a final 'patch' on the object. This cleanup process can sometimes be slow.

The issue arises when the API call completes before the database transaction from the ngOnDestroy method, causing the user to see outdated data upon returning to the list.

  ngOnDestroy(){
    this.destroy$.next();
    this.template.template_items.forEach((item, index) => {
      // mark uncompleted items for deletion
      if (!item.is_completed) {
        this.template.template_items[index]['_destroy'] = true;
      };
    });
    // NOTE 
    // We don't care about result, this is a 'silent' save to remove empty items,
    // but also to ensure the final sorted order is saved to the server
    this._templateService.patchTemplate(this.template).subscribe();
    this._templateService.selectedTemplate = null;
  } 

I am aware that synchronous calls are not recommended due to UI/browser blocking. While there are various solutions available, it's challenging to determine the best approach, especially considering Angular's lack of support for sync requests.

One idea I considered was having ngOnDestroy send a 'marker' to the API to label the object as 'processing'. The list component could then check for this marker and display a 'refresh stale data' button for any objects in that state (likely just one item - the most recently edited by the user). However, this workaround seems cumbersome and requires additional code compared to changing to a synchronous call.

I have not been able to find clear examples of similar issues apart from this synchronous one.

EDIT

Note that the child component already has a CanDeactivate guard in place, prompting the user to confirm changes before leaving. If the user confirms, the cleanup code in ngOnDestroy executes. In this context, the user is not discarding changes but rather awaiting server processing of the final data set. Ideally, the user should not leave until ngOnDestroy finishes - how can I enforce waiting for the API call to complete?

My CanDeactivate guard is implemented similarly to the official documentation for the Hero app, utilizing a dialog service to query the user's intention to stay or proceed away:

  canDeactivate(): Observable<boolean> | boolean {
    console.log('deactivating');
    if (this.template.template_items.filter((obj) => { return !obj.is_completed}).length < 2)
      return true;

    // If there are empty items, prompt user with the dialog service
    return this._dialogService.confirm('You have some empty items. Is it OK if I delete them?');
  }

Although moving the cleanup code from ngOnDestroy to a "YES" method handler in the dialog may seem like a solution, the issue remains as the YES handler would still complete before the API, resulting in the same problem.

UPDATE

Based on feedback received, I believe the solution may involve modifying the guard from:

    return this._dialogService.confirm('You have some empty items. 
        Is it OK if I delete them?');

to

    return this._dialogService.confirm('You have some empty items.
        Is it OK if I delete them?').subscribe(result => {
      ...if yes, call the API and return true...
      ...if no, return false...
      });

Answer №1

Exploring various options based on the setup of your app, data flow, and user experience flow is crucial. One method worth considering is the CanDeactivate guard, which ensures that users cannot leave a route until specific conditions are met, such as resolving an Observable<boolean> or Promise<boolean> to true.

This approach allows for asynchronous handling while waiting for server-side changes confirmation.

[UPDATE]

The actual implementation may vary depending on how user confirmation is handled, but here is a basic example:

waitForServiceToConfirmWhatever(): Observable<boolean> {
    return yourService.call(); // Returns Observable<boolean> emitting true when server tasks are completed
  }

canDeactivate(): Observable<boolean> {

    if(confirm('Do you want to leave?')) {   
      return this.waitForServiceToConfirmWhatever();
    } else {
      return Observable.of(false);
    }
  }

Answer №2

A possible solution that comes to mind is organizing your list on the client side. You can store the list as a JavaScript array or object and display the user interface accordingly. When editing in the details screen, mark the item as stale and have the service called on ngOnDestroy clear it while updating other connected data.

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

Is there a way to dynamically update the text of $ionicPopup's subTitle in Ionic?

I am currently attempting to modify both the value and style of the subText attribute linked to an $ionicPopup within my app. Despite searching extensively, I have been unable to uncover a viable method for accomplishing this task. Is there a way to achi ...

An error has occurred: Expected a string as the element type in React when attempting to update the state

I encountered an issue while trying to update the state after fetching data. Error: Element type is invalid - expected a string (for built-in components) or a class/function (for composite components), but received: undefined. This could be due to forgett ...

"Looking to replace a character class pattern using regex in JavaScript? Here's how you can easily

I have a string: "\W\W\R\" My goal is to transform this string using regular expressions into: <span>W</span><span>W</span>\R This is the code I'm currently using: "\W\W\R".replace(/&b ...

document ready function in the Microsoft AJAX client side library

The Microsoft AJAX client-side library contains various functions that imitate the server-side Page Life Cycle and conditions like if (!Page.IsPostBack). I am unsure about which client-side function corresponds to the equivalent server-side method. What is ...

The symbol 'submitted' has not been declared

I have been working on implementing client-side validation in Angular using ReactiveForms. I encountered an error stating "Identifier 'submitted' is not defined. 'FormGroup' does not contain such a member" on this line: <div *ngIf=&q ...

What could be causing the server to return an empty response to an ajax HTTP POST request?

Attempting to make a POST request using ajax in the following manner: $.ajax({ type: "POST", url: 'http://192.168.1.140/', data: "{}", dataType: "json", ...

Tips for successfully retrieving a boolean value from an ASP.Net JavaScript AJAX request using a C# method

Query: Is there a way to call a C# function from JavaScript code on an .aspx webpage to get authentication results based on a username and password? Here is the JavaScript AJAX POST request I am currently using: $.ajax({ type: "POST", ...

Ensuring the completion of all validations in Angular 4

Currently, I'm working on a project that involves 3 FormControls. I am in need of a validation process that ensures either all three have values selected or none at all. Is there a method to achieve this type of validation? ...

Sometimes the Navbar options fail to show up consistently on the Navbar bar

I recently launched my website at campusconnect.cc Unfortunately, I've noticed that when resizing the window, the navbar options are shifting up and down. Can anyone help me identify the issue and provide guidance on how to resolve it? ...

Guide to setting up and launching a JavaScript/Vue GitHub repository on your local machine

I have a cloned app located here: cvss-v4-calculator that I want to run locally for debugging with VS Code or a similar tool. However, I'm encountering difficulties in setting it up. I've been attempting to run this as a web page using node.js, b ...

Troubleshooting Issue with Internet Explorer failing to update Asp.Net MVC3 Partial View

I am experiencing an issue with a page that includes a div for a partial view loaded via an ajax request. $.ajax({ url: 'CompleteSessions', success: function (data) { var selector = $('#complete-session-sect ...

Is there a way for me to extract the true text content that is concealed within the page source code?

Is there a way to extract the hidden text "2015-10-31" from a webpage, even though it is not visible in the page source? I am able to scrape the right side of the HTML, but I need to access the value on the left side. I have tried using Selenium to automat ...

Incorporated asynchronous functionality, struggling to integrate it into the code

Previously, I used to utilize the following code for handling state: //get state MyClass.prototype.getState = function(key) { var value; switch(this._options.type){ case "cookie": value = $.cookie(key); ...

The AJAX function failed to trigger another JavaScript function after successfully completing its task

Trying to figure out how to execute a function after successful AJAX post request. The function I want to call is: function col() { var $container = $(".post-users-body"); $container.imagesLoaded(function() { $container.masonr ...

Save the result of a terminal command into an sqlite database

When I run a particular shell command in node js, the output is displayed on the console. Is there a method to store this output in a variable so that it can be POSTed to an Sqlite database? const shell = require('shelljs'); shell.exec('a ...

Is it possible for me to hand over control to a child process and retrieve the result in Node.js?

Recently, I encountered an issue where multiple simultaneous GET requests to my Node.js server caused it to become overwhelmed and unresponsive, leading to timeouts for clients (503, service unavailable). Upon thorough performance analysis, I discovered t ...

NextJS application failing to display SVG icon in the absence of internet connection

https://i.stack.imgur.com/M9reE.jpg https://i.stack.imgur.com/Yyg4g.jpg Upon inspection of the provided images, it is evident that the src URL points to a location within the nextjs public folder. The issue arises when there is no internet connection - i ...

Tips for keeping several buttons in the spotlight: HTML/CSS/JS

Looking for a solution to keep multiple buttons toggled on? I'm not very familiar with JavaScript, but I know that adding a class on click won't work if there's already a class set. Maybe giving the element an ID could be a possible solution ...

What is the best way to forward a file upload request from a Next.js API to another API?

Trying to crop an image within a Next.js application, then sending it through an API route within the app before reaching an external API endpoint is proving to be a challenge. The process works fine without going through the API route, but once that step ...

Preventing an Angular component from continuing to execute after clicking away from it

At the moment, I have a sidebar with clickable individual components that trigger API calls to fetch data. However, I've noticed that even when I click off a component to another one, the old component continues to refresh the API data unnecessarily. ...