Steps for Signing Up for a Collaboration Service

I'm struggling to understand how to monitor for new values in an observable from a service. My ultimate objective is to integrate an interceptor, a service, and a directive to show loading information to the user. I have set up an interceptor to listen for http calls:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpResponse } from '@angular/common/http';
import { Observable, pipe } from 'rxjs';
import { LoadingService } from '../loading.service';
import { map, finalize } from 'rxjs/operators';

@Injectable()
export class LoadingInterceptor implements HttpInterceptor {
  constructor(private loadingSrv: LoadingService) {}

  public intercept(req, next): Observable<HttpEvent<any>> {
    if (req.url === 'graphql') {
      console.log('first', req);
      this.loadingSrv.saveRequest(req);
    }
    return next.handle(req).pipe(
      map(el => {
        if (req.url === 'graphql') {
        }
        return el;
      }),
      finalize(() => {
        console.log('final', req);
      })
    );
  }
}

If a request is detected, it should trigger the loading service and execute a saving function.

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class LoadingService {
  public loadingQueries: BehaviorSubject<[]> = new BehaviorSubject(null);
  constructor() {}
  saveRequest(req) {
    this.loadingQueries.next(req);
  }
}

The loading service will emit the new request value to the behavior subject. Now, my goal is to subscribe to this BehaviorSubject from a directive.

import { Directive, Input, OnInit, TemplateRef, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
import { LoadingSpinnerComponent } from './loading-spinner.component';
import { LoadingService } from './loading.service';

@Directive({
  selector: '[showLoadingSpinner]'
})
export class ShowLoadingSpinnerDirective implements OnInit {
  @Input('showLoadingSpinner') query: any;

  constructor(
    private viewContainerRef: ViewContainerRef,
    private templateRef: TemplateRef<any>,
    private loadingSpinner: LoadingSpinnerComponent,
    private factoryResolver: ComponentFactoryResolver,
    public loadingSrv: LoadingService
  ) {}

  ngOnInit(): void {
    const factory = this.factoryResolver.resolveComponentFactory(LoadingSpinnerComponent);
    console.log(this.query);
    this.loadingSrv.loadingQueries.subscribe(console.log);
  }
}

My issue now is that the subscriptions are not recognizing new values. Perhaps because the service here is a new instance? How can I ensure the directive listens for any changes to detect when a query is initiated and completed?

Answer №1

Here is a potential solution that might suit your needs. While I cannot determine the exact issue at hand, my suggestion would be to keep the BehaviorSubject private. Additionally, it is crucial to remember to unsubscribe in your component.

For your loading service:

export interface LoadingState {
  req: any;
}

let _state: LoadingState = {
  req: null,
};

@Injectable({
  providedIn: 'root',
})
export class LoadingService {
  private store = new BehaviorSubject<LoadingState>(_state);
  private state$ = this.store.asObservable();

  req$ = this.state$.pipe(
    map((state) => {
      return state.req;
    }),
    distinctUntilChanged()
  );

  constructor() {}
  saveRequest(req) {
    this.updateState({ ..._state, req });
  }

  private updateState(state: LoadingState) {
    this.store.next((_state = state));
  }
}

In your component:

constructor(private loadingSrv: LoadingService) {}
private onDestroy = new Subject<void>();
req$: Observable<LoadingState> = this.loadingSrv.req$;
ngOnInit() {
this.req$.pipe(takeUntil(this.onDestroy)).subscribe((value) => {
console.log(value);
});
}
ngOnDestroy() {
this.onDestroy.next();
this.onDestroy.complete();
}

Answer №2

To resolve the issue, the decision was made to place the service in a module that is not lazily loaded.

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

Steps for setting up an auth guard:1. Define a

I am facing an issue with implementing two guards in my Angular application. The first guard is supposed to restrict unauthorized users from accessing certain pages, while the second guard is meant to prevent authorized users from accessing the "sign-in" a ...

Gradle synchronization in IntelliJ causing missing folders in WAR Artifact

Currently, I am working on a Spring MVC application that incorporates TypeScript. The TypeScript code is transpiled using a Gradle task from the directory src/main/ts to build/ts. Subsequently, the resulting JavaScript files are added to the WAR file usin ...

Ways to dynamically link a JSON response object to an entity?

In my ng2 implementation, I have a user.service.ts file that calls a REST service and returns JSON data. The code snippet below shows how the getUser function retrieves the user information: getUser(id: number): Promise<User> { return this.http. ...

Utilizing TypeScript to define the parameter of a method within a generic interface by extracting a value from the generic type

In search of defining a versatile interface that can manage any Data type, I came up with an idea. This interface includes a dataKey property which simply holds a value of keyof Data. Additionally, it features a handler function where the parameter type sh ...

The edited input is not being shown on the console when using the PUT method

I retrieved the data for the input fields (title and body) from this specific source (https://jsonplaceholder.typicode.com/posts). My goal now is to modify the text in either the title or body, so that when I use console.log(), it will show the updated tit ...

What is the best way to isolate the CSS of individual components in Angular 2?

For the first component: CSS-- ngx-dnd-container { color:black; background-color: white; } HTML- <ngx-dnd-container [model]="targetItemsA" dropZone="multiple-target-a" </ngx-dnd-container> For the sec ...

Error with Array type encountered in Typescript's find method

I am encountering an issue with code that looks like this: type X = { test: number; x: number; }[]; type Y = { test: number; y: number; }[]; type Z = { test: number; z: number; }[]; export const testFunc = (arg: X | Y | Z) => { return a ...

The production build of Angular 2 with special effects amplification

I am currently working on an Angular 2 Beta 8 app that I need to bundle and minify for production deployment. Despite configuring the system to generate a Single File eXecutable (SFX) bundle, I am encountering issues with creating a minified version of the ...

React component showing historical highchart data when navigating through previous and next periods

I developed this element to showcase a Highchart. It's utilized within a dashboard element that I access from an item in a list. It mostly works as intended, but not entirely. When I move to the dashboard for item A, everything functions correctly. H ...

Encountering a discord bot malfunction while on my Ubuntu server

My discord bot runs smoothly on my Windows 10 setup, but when deployed to the server running Ubuntu Server 20, it encounters a specific error. The issue arises when trying to handle incoming chat messages from the server. While I can read and respond to m ...

How can I retrieve the value of a promise in Promise.map?

I am currently working on a project that involves saving data to a database using Mongoose. One specific field in the database is the 'thumbnail' field, which needs to be filled with a base64 converted file after the file is uploaded to the serve ...

Creating a HandleCredentialResponse function in Angular version 14 for implementing the "Sign in with Google" feature using Typescript

In the process of building a very simple angular version 14 application, I am working on displaying a 'Sign in with Google button' and incorporating the login functionality. For information about the new method of Sign in With Google, you can re ...

The array containing numbers or undefined values cannot be assigned to an array containing only numbers

Currently facing an issue with TypeScript and types. I have an array of IDs obtained from checkboxes, which may also be empty. An example of values returned from the submit() function: const responseFromSubmit = { 1: { id: "1", value: "true" }, 2: ...

There seems to be an issue with the request header field Authorization, as it is not permitted by the Access-Control-Allow-Headers in

My project involves using Angular 2 for the client side and Laravel 5.4 for the server side. I have set up APIs in Laravel and am making requests to them from Angular 2. In Laravel, I have configured Oauth 2 passport service to authenticate all APIs. For ...

Difficulty Converting Array of Objects to Proper Type with Q.Promise and KO.mapping

I have encountered an issue while trying to filter an observable array. It seems that the ko.utils.arrayFilter method is converting all my model's field names to lowercase, causing unexpected behavior. I should mention that this project involves Types ...

The element does not have a property named "emit" in its type

Trying to transfer data between components using Subject through services resulted in the error message below: 'Property 'emit' does not exist on type 'Subject(any)'. This is what was attempted: component.ts file import { Compo ...

Creating a digital collection using Vue, Typescript, and Webpack

A short while back, I made the decision to transform my Vue project into a library in order to make it easier to reuse the components across different projects. Following some guidelines, I successfully converted the project into a library. However, when ...

Can you explain the distinction among the various FormControl initialization techniques?

Can you discern the variance among the following methods: input: new FormControl({}, inputValidatorFn()) input: [{}, inputValidatorFn()] input: formBuilder.control({}, inputValidatorFn()) They appear to function identically. Is there truly no disparit ...

Utilizing Typescript for constructor parameter assignments

Within my codebase, there exists an interface: export interface IFieldValue { name: string; value: string; } This interface is implemented by a class named Person: class Person implements IFieldValue{ name: string; value: string; const ...

When exporting data to Excel, the date is automatically adjusting based on the timezone. Is there a way to prevent this from happening

Whenever I attempt to export data to excel in angular, I encounter an issue with time zones. The date in the database is set in timezone 'x', while I am exporting data from timezone 'y'. As a result, the exported data in Excel displays ...