How can the service receive the return value from a subscribed subject?

I have a question about whether it is possible to retrieve the value from a call to Subject.next(). Can you suggest any other approaches on how to receive a response in the given scenario?

My current situation involves a notify service that is used throughout the app. It displays a message box to the user, at minimum with an 'OK' button, and I need to be able to determine when the user clicks on this button:

import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class NotifyMessagesService {
   private setMessageBoxData = new Subject<INotifyMessage>();

   constructor() { }

   getMessageBoxData(): Observable<INotifyMessage> {
      return this.setMessageBoxData.asObservable();
   }
    
   public notifyMessageBox(message: string, header?: string)/*: Promise<any>*/ {
      /*return new Promise(resolve => {*/
      
      this.setMessageBoxData.next({ message: message, header: header });
      /*resolve();*/ //The response from next() should go here
      /* });*/
   }
}

export interface INotifyMessage {
  header?: string;
  message: string;
}

I also have a component that subscribes to this service:

export class NotifyControllerComponent implements OnInit, OnDestroy {

@ViewChild('messageBox', null) messageBox: MessageBoxComponent;

subscription: Subscription;

constructor(private notifyService: NotifyMessagesService) {

   this.subscription = this.notifyService
      .getMessageBoxData()
      .subscribe(message => {
        if (message) {
          this.messageBox.show(`${message.message}`
            , `${message.header}`).then(() => {
              //Here, I need to notify NotifyMessagesService that the user clicked on the message box
            });
        }
      });

    }

    ngOnInit() { }

    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
}

I would appreciate your advice on updating the code examples to achieve the following: Whenever I call the service, it should return after the user confirms the message box.

export class AnyComponent implements OnInit{
   constructor(private notifyMessagesService: NotifyMessagesService){
   }

   showMessage(){
      this.notifyMessagesService.notifyMessageBox('Hi','it works').then(res=>{
         console.log('User reaction ' + res);
         //Code continues here
      });  
   } 
}

-> Therefore, I believe the service method should be updated to return a Promise or Observable (as mentioned in the examples), but how can this be done?

Answer №1

Create a Custom Confirmation Dialog with Callback Support

This method involves using the ComponentFactoryResolver to generate a dialog component that can be dynamically constructed whenever a confirmation dialog is needed for the user.

Challenges to Address when Implementing this Approach

  • Create a template component for the confirmation dialog
  • Develop a service to create new instances of the dialog
  • Obtain a ViewContainerRef within the service.

The last point requires some compromise since services do not have their own ViewContainerRef to attach to. Thus, it's necessary to organize the application in a way that allows the dialog service to access a reference before creating the dialog component.

Confirmation Dialog Component

Let's examine the component responsible for serving as our confirmation dialog.

It is a straightforward component with buttons and a callback function for later use.

[Component code here]
[HTML template section here]
[Interface for Message Option here]

CSS details excluded for brevity

Dialog Service

Next, we look at the service tasked with assembling our confirmation dialog.

[Service code snippet here]

The service leverages the ComponentFactoryResolver and ViewContainerRef to create a new instance of the ConfirmDialogComponent.

Additionally, critical references are passed down to the new ConfirmDialogComponent instance, such as the newly created ComponentRef, enabling removal of the dialog post user action.

Setting up the ViewRef

The current solution faces an issue where the ViewRef remains undefined.

To rectify this, inject the service into the component that initializes your application and set the ViewRef from there.

Sample app.component.ts:

[App component setup code snippet here]

You can now employ the DialogService anywhere within your Angular application to produce Confirmation Dialogs seamlessly.

Stackblitz Demo

Explore usage example

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

When working with the Google Sheets API, an error occurred: "this.http.put(...).map is not a valid

Having difficulty with a straightforward request to the Google Sheets API using the PUT method. I followed the syntax for http.put, but an error keeps popping up: this.http.put(...).map is not a function. Here's my code snippet: return this.http ...

Performing multiple asynchronous tasks using RxJS by running Array.prototype.map in parallel batches or queues

Imagine having an array of variables, such as: [Sasha, Misha, Caitlyn, ...String] (string[]) with a sizable length of about 10k elements. If you want to run an asynchronous parallel task with these elements, but not all at once like Promise.all, rather in ...

Intellisense for dispatch types in Redux Toolkit

After following the documentation for redux toolkit with typescript, I implemented my own useDispatch hook as shown below export const useAppDispatch = () => useDispatch<AppDispatch>() and used it in components like this const dispatch = useAppDi ...

Tips for utilizing the "this" keyword in TypeScript

As a newcomer to TypeScript, I am seeking assistance on how to access the login service within the authenticate function. Despite using the 'this' keyword to retrieve the login service, it seems ineffective. Additionally, I find myself puzzled by ...

How can I access properties of generic types in TypeScript?

Converting the generic type to any is a valid approach (The type E could be a typescript type, class, or interface) of various entities like Product, Post, Todo, Customer, etc.: function test<E>(o:E):string { return (o as any)['property' ...

Seeking assistance with managing Yarn workspaces

My current project involves working on a React Native application for a client. After I had already written a significant amount of code, my client requested a new feature to be added. This feature should have been simple to implement, but due to the compl ...

Dependency on Angular's HTTP service inside a component

I've been experimenting with loading data from a static JSON file as part of my journey to learn angular templating. After some searching online, I came across a few examples. However, I want to steer clear of implementing a service until I have a be ...

What happens when two style() functions are passed into the query() function for Angular Animations?

As someone who is relatively new to angular animations, I have reviewed the angular.io animation documentation multiple times in order to grasp how everything functions. While I believe I have a decent understanding, there are certain scenarios that the do ...

Replace Formik with useFormik to streamline your code

I have implemented Formik/Yup for validation on a page that triggers a GraphQL mutation. The code is functioning as expected: export default function RemoveUserPage() { const [isSubmitted, setIsSubmitted] = useState(false); const [isRemoved ,setIsRemo ...

Error: Interface declaration for _.split is missing in the Lodash.d.ts file

For my current typescript project that heavily relies on Lodash with lodash.d.ts, I've encountered an issue with the _.split function not being implemented yet. It's listed under the 'Later' section in the .ts file. I need to find a wo ...

What is causing the failure of the state to be inherited by the child component in this scenario (TypeScript/React/SPFX)?

For this scenario, I have a Parent class component called Dibf and a Child class component named Header. While I can successfully pass props from the Parent to the child, I am encountering difficulties when trying to pass state down by implementing the fo ...

Unknown Angular component identified

I'm currently working on an application with the following structure: app |-- author |-- |-- posts |-- |-- |-- posts.component.html |-- |-- author.component.html |-- |-- components |-- |-- tag |-- |-- |-- tag.component.ts |-- home |-- |-- home.comp ...

Is there a way to update components in Angular without affecting the current URL?

I want to update a component without changing the URL. For example, I have a component called register. When I visit my website at www.myweb.com, I would like to register by clicking on sign up. How can I display the register component without altering the ...

Unnecessary Attributes in Type that Should be Automatically Inherited by Child Component

Within my child component, I am creating the Props interface and incorporating it into the React.Component. These Props must then be passed from the parent component to the child component. So far, everything is clear and logical. However, when I extend ...

Enhance your production mode with @ngrx/store-devtools

Currently, I have integrated @ngrx/store-devtools instrumentation with the Chrome Extension. Is it advisable to turn off this feature for production mode? ...

Troubleshooting offline pagination with dynamic MatTable containing matInputs (Angular 5 Material Design)

I have an issue with my component that contains an empty form with matInputs, as well as a mat-table with matInputs in the rows, all enclosed in mat-cards. The number of rows in the table is dynamic and based on another input called 'range'. So, ...

Challenges encountered when sending an HTTP post request in Ionic 2 with Angular 2

Whenever I try to make a post request in my ionic2 application, I encounter an error without any specific message. It seems like there is something wrong with my Angular2 post request. Below is the function I am using for the request: load(username, pass ...

When utilizing makeStyles in @mui, an error may occur stating that property '' does not exist on type 'string'

I am stuck with the code below: const useStyles = makeStyles(() => ({ dialog: { root: { position: 'absolute' }, backdrop: { position: 'absolute' }, paperScrollPaper: { overflow: 'visib ...

Encountering notifications and issues pertaining to conflicting dependencies after integrating the angular-oauth2-oidc dependency into the package.json file

I am currently working on an Angular project and wanted to share my package.json file for reference: { "name": "angular.io-example", "version": "0.0.0", "description": "Example project from ...