Observable doesn't respond to lazy loaded module subscriptions

I am trying to understand why my lazy loaded module, which loads the test component, does not allow the test component to subscribe to an observable injected by a test service.

index.ts

export { TestComponent } from './test.component';
export { TestModule } from './test.module';

test.component.ts

import { Component, OnInit } from '@angular/core';
import { TestService } from './test.service';
import { Observable } from 'rxjs';

@Component({
    selector: 'test',
    template: `
        <p>{{test | async}}</p>
  `,
})
export class TestComponent {
    test: Observable<number>;
    constructor(private testService: TestService) { 
        this.test = this.testService.getObservable();
    }
}

test.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TestComponent } from './test.component';
import { TestService } from './test.service';

@NgModule({
    declarations: [TestComponent],
    imports: [
        CommonModule,
    ],
    providers: [TestService]
})
export class TestModule { }

test.service.ts

import { Injectable } from '@angular/core';
import { from, Observable } from 'rxjs';
import { delay } from "rxjs/operators";

@Injectable()
export class TestService {
    getObservable(): Observable<number> {
        return from([...Array(10).keys()].reverse())
            .pipe(
                delay(1000)
            )
    }
}

app.component.ts

import { Component, ViewChild, ViewContainerRef, Compiler, Injector, Type, NgModuleFactory } from '@angular/core';
import { TestModule } from './test';

@Component({
    selector: 'app-root',
    template: `
        <ng-container #vc></ng-container>
  `,
    styles: []
})
export class AppComponent {
    @ViewChild('vc', { read: ViewContainerRef }) containerRef: ViewContainerRef;

    constructor(private compiler: Compiler, private injector: Injector) {
    }

    async ngOnInit(): Promise<void> {
        await this.loadComponent();
    }

    async loadComponent(): Promise<void> {
        const { TestComponent, TestModule } = await import('./test');
        const moduleFactory = await this.loadModuleFactory(TestModule);
        const moduleRef = moduleFactory.create(this.injector);
        const factory = moduleRef.componentFactoryResolver.resolveComponentFactory(TestComponent);
        this.containerRef.createComponent(factory);
    }

    private async loadModuleFactory(moduleFactory: Type<TestModule>): Promise<NgModuleFactory<TestModule>> {
        if (moduleFactory instanceof NgModuleFactory) {
            return moduleFactory;
        } else {
            return await this.compiler.compileModuleAsync(moduleFactory);
        }
    }
}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }

The app.module.ts is included here for completeness.

After compiling all these code snippets, the text within the p tags is not being displayed.

Answer №1

It turns out that the reason why I wasn't seeing the expected result of my countdown was due to a rxjs issue. I'm puzzled as to why my initial approach didn't yield the desired outcome:

from([...Array(10).keys()].reverse()).pipe(delay(1000));

To me, this seemed like a logical way to create a countdown. After searching on stackoverflow, I discovered alternative methods to achieve the correct functionality. Like this one:

const timer = 10; 
interval(1000).pipe(take(timer), map(time => (timer - 1) - time));

Answer №2

After reviewing your original example, I came up with a code snippet that might be helpful:

  numbers$: Observable<number> = from(
    Array.from(Array(10).keys()).reverse()
  ).pipe(
    concatMap(n => of(n).pipe(delay(1000))),
    tap(console.log)
  );

Here are a few points to consider:

In TypeScript, I had to avoid using the spread operator because of this issue: https://github.com/Microsoft/TypeScript/issues/18247

The delay operator delays the start of each emission, not the interval between emissions.

By turning each number into an Observable, delaying it, and then using concatMap to wait, the count down effect is achieved.

In terms of readability, the alternative method you mentioned appears clearer:

  numbers$ = interval(1000).pipe(
    take(10),
    map(time => 9 - time)
  );

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 method for retrieving GET parameters in an Angular2 application?

Is there a way in Angular2 to retrieve GET parameters and store them locally similar to how sessions are handled in PHP? GET Params URL I need to obtain the access_token before navigating to the Dashboard component, which makes secure REST Webservice cal ...

An issue has occurred: it seems that the property cannot be accessed because `this.child` is undefined

Is there a way to call the function "initMap" that is defined in the child component "UpdatePinComponent", from the parent component named "ApiaryComponent"? Below is a snippet of the TypeScript code from the parent component: import { AfterViewInit, Compo ...

Please ensure that the table contains all the records corresponding to the respective days

I am struggling with figuring out how to display a record of classes in my table view. The UX prototype I need to follow is shown https://i.stack.imgur.com/CISYn.png (the days of the week are in Portuguese: horario = time, segunda = Monday, terça = Tuesda ...

Resolving the active tab problem within Angular 2 tab components

Can anyone assist in resolving the active tab problem within an angular 2 application? Check out the Plunker link I am using JSON data to load tabs and their respective information. The JSON format is quite complex, but I have simplified it here for cla ...

An issue was encountered at node_modules/@fullcalendar/core/main.d.ts(1196,54), error TS1144: Expecting either '{' or ';'

When attempting to execute npm run build in my project, I encountered the following error: ERROR in node_modules/@fullcalendar/core/main.d.ts(1196,54): error TS1144: '{' or ';' expected. node_modules/@fullcalendar/core/main.d.ts(1197,34 ...

Heroku is having trouble deploying an app that has both frontend and backend components merged together

I am currently facing an issue with my Angular frontend and Node.js backend app when deploying it to Heroku. The build and compile process is successful, but it seems that only the backend is running on Heroku when attempting to access the app. I have foll ...

Troubleshoot: ng-bootstrap Carousel Functionality Issue

While testing the various components on ng-bootstrap, I encountered an issue with getting the carousel to work. Strangely enough, all the other ng-bootstrap components are functioning perfectly. Upon implementing the code from , the result is a blank white ...

What is the reason for the typescript check failing?

When attempting to check for the existence of an attribute using if statement, I encountered an error. Can anyone explain why this happened? I would appreciate any insights on this issue. ...

typescript error: referencing a variable before assigning a value to it in function [2454]

I am currently in the process of creating a store using nextJS I have two variables that are being assigned values from my database through a function let size: Size let ribbonTable: Ribbon async function findSizeCategory(): Promise<v ...

Angular 2 wrap-up: How to seamlessly transfer filter data from Filter Component to App Component

A filtering app has been created successfully, but there is a desire to separate the filtering functionality into its own component (filtering.component.ts) and pass the selected values back to the listing component (app.ts) using @Input and @Output functi ...

JavaScript: exporting everything from ... causing excessive bloat in the build file

After building my react-app with create-react-app, I noticed a decline in performance. Here is the structure of my project: /store actions.ts reducers.ts /module1 module1.actions.ts module1.reducers.ts /moduleN moduleN.actions.ts m ...

Maintain the nullability of object fields when casting

I have been working on a type called DateToNumber that converts all the Date properties of an object to number. Here is what I have come up with so far: type LiteralDateToNumber<T> = T extends Date ? number : T extends Date | null ? number | nu ...

Exploring Angular (5) http client capabilities with the options to observe and specify the response type as 'blob'

Situation: I'm facing a challenge in downloading a binary file from a backend system that requires certain data to be posted as JSON-body. The goal is to save this file using File-Saver with the filename specified by the backend in the content-disposi ...

Having trouble establishing a connection with mongoose and typescript

When attempting to establish a connection using mongoose, I consistently encounter the errors outlined below. However, if I use MongoClient instead, everything functions as expected. import connectMongo from '../../lib/connectMongo' console.log( ...

If two requests are made at the same time, they will both yield identical results

Encountering an issue where running two separate HttpClient requests to my Spring Boot backend yields the same result for both requests (the first request's result). This occurs approximately 30% of the time: //request 1 with url_1= "http://local ...

Angular | The parameter type 'User[]' is incompatible with the expected parameter type 'Expected<User>' and cannot be assigned

While testing Angular, I encountered this error that has me stumped. The issue seems to be with the user inside the toBe() function. This error is occurring in the file user.service.spec.ts it('should call getUsersById', () => { const user ...

"Acquiring the version number in Angular 5: A step-by-step

How can I retrieve the version from my package.json file in Angular 5 project? I am using Angular-Cli: 1.6.7 and npm 5.6.0 Here is a snippet from my enviroment.ts file: export const enviroment = { VERSION: require('../package.json').versio ...

Tips for determining the datatype of a callback parameter based on the specified event name

Let's say we have the following code snippet: type eventType = "ready" | "buzz"; type eventTypeReadyInput = {appIsReady: string}; interface mysdk { on:(event: eventType, cb: (input: eventTypeCallbackInput) => void) => void } mysdk.on("ready", ...

I am looking to access a public method from a different component in Angular 2

Trying to access the headerExpand property from app.component is causing an error message in the console: metadata_resolver.js:559 Uncaught Error: Invalid providers for "Page1" - only instances of Provider and Type are allowed, got: [?undefined?] page1 ...

Challenges arise when working with Vue 3.2 using the <script setup> tag in conjunction with TypeScript type

Hey there! I've been working with the Vue 3.2 <script setup> tag along with TypeScript. In a simple scenario, I'm aiming to display a user ID in the template. Technically, my code is functioning correctly as it shows the user ID as expect ...