Turning off @Output as Observable: A step-by-step guide

I have a query regarding unsubscribing Outputs in Angular. While I am aware that EventEmitter is automatically cleaned up, there was a time when I needed to use an Observable as my Output. Specifically, I wanted to take an Output that emitted events at most once per second. This led me to write the following code:

@Output() loadNextEvent: Observable<any>;
loadNextSubject = new Subject();

constructor(private el: ElementRef) {
    this.loadNextEvent = this.loadNextSubject.asObservable()
        .throttleTime(1000); // emitting event once per second
    }

emit() {
    this.loadNextSubject.next('new event');
}

It seemed to work fine initially. However, the issue arose with unsubscribing. Despite finding a solution on StackOverflow, I still struggled with determining the correct approach. In my scenario:

@Output() loadNextEvent: Observable<any>;
loadNextSubject = new Subject();

constructor(private el: ElementRef) {
    this.loadNextEvent = this.loadNextSubject.asObservable()
        .takeUntil(this.loadNextSubject) // does this make sense?
        .throttleTime(1000); // emitting event once per second
    }

emit() {
    this.loadNextSubject.next('new event');
}

ngOnDestroy() {
    this.loadNextSubject.complete();
}

Question: Is this the right way to unsubscribe from an observable Output? Does .takeUntil(this.loadNextSubject) serve any purpose? Or perhaps does .asObservable() ensure that the Observable is cleared when the Subject is completed? Can anyone provide guidance on resolving my dilemma or suggest a better alternative than using Observable as an Output in my case?

Answer №1

For utilizing the takeUntil method, it's essential that the notifier Observable emits a next notification rather than simply completing. Therefore, the proper way to achieve this is as follows:

ngOnDestroy() {
    this.loadNextSubject.next();
    this.loadNextSubject.complete();
}

Additionally, in this scenario, there is no need for using asObservable(). Subjects inherently function as Observables, so applying asObservable() unnecessarily encapsulates it within another Observable.

Furthermore, there was an issue in Angular 5 causing memory leaks when operators were chained with EventEmitter (the disposal of the chain was not properly executed). For more information regarding this matter, refer to this link.

The resolution for this problem can be found at this source which should have been implemented since the release of Angular 6.

It seems like you might be encountering this issue at the moment. A simple workaround until Angular 6 is to apply asObservable() before introducing any operators. More on this can be found in this comment.

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

How to access an element through the router-outlet in Angular 6?

<side-navigation [navigationTitle]="navTitle"></side-navigation> <router-outlet> </router-outlet> Within my project, I have a navigation bar located in the root component. I have set up [navigationTitle] as an @Input Decorator wit ...

Can you explain the distinction between 'rxjs/operators' and 'rxjs/internal/operators'?

When working on an Angular project, I often need to import functionalities like the Observable or switchMap operator. In such cases, there are two options available: import { switchMap } from 'rxjs/operators'; or import { switchMap } from ' ...

The information being sent from Angular is not being successfully transmitted to the XAM

Here is my Angular service post method: getUserDetails(username , password) { alert(password); return this.http.post<myData>("http://localhost/test/api/auth.php", { username, password }); } This is the structure of my PHP file: <?php ...

Angular: merging multiple Subscriptions into one

My goal is to fulfill multiple requests and consolidate the outcomes. I maintain a list of outfits which may include IDs of clothing items. Upon loading the page, I aim to retrieve the clothes from a server using these IDs, resulting in an observable for e ...

Iterating through an array with ngFor to display each item based on its index

I'm working with an ngFor loop that iterates through a list of objects known as configs and displays data for each object. In addition to the configs list, I have an array in my TypeScript file that I want to include in the display. This array always ...

Tips for triggering multiple components in Angular2 with a single event

My current project involves an input component, an output component, and a processing service. The goal is to allow the user to input a string, have it processed by the processing service, and then display the processed message in the output component. How ...

Send information to the child.component.ts file, not the child template

A scenario I am working on involves passing a value from a parent component to a child component. However, prior to displaying this value in the child.component.html file, I have a requirement to increment it by 2 within the app.component.ts file, and then ...

What is the reason behind the input text field not preserving its value when disabled?

Currently, I am working on a basic input field that utilizes Angular within StorybookJS. However, I have encountered an issue where the input text field does not maintain its value when the disabled attribute is set to true. For example, if I manually typ ...

The HTML template remains unchanged unless explicitly triggering detectChanges() with change detection set to onpush

In my Angular component, I am utilizing change detection on push. The component includes an input that gets modified by the component when the route changes. However, I noticed that simply assigning a new reference to the input and making modifications d ...

Access the JSON data containing sub array values and showcase them on an HTML page by utilizing ngFor

Greetings! I am currently working on a web application where I need to showcase student data that is being received in JSON format. Below is the TypeScript code snippet that outlines the structure of the student data: export interface studentData{ ...

"Encountering a Challenge: Cannot Assign Array to ngFor Directive in Ionic App, Displaying

I have encountered an issue while fetching product categories using API. The problem lies in the fact that the categories are being retrieved as an object instead of an Array which is required for *ngFor to work in Ionic. Any assistance on how to define th ...

Is KeyValueDiffers within DoCheck limited to working with just a single object per component?

Initially, my ngDoCheck method worked perfectly with just this line: var productChanges = this.differ.diff(this.myProduct); Then I decided to add another object from my component and included the following line: var companyChanges = this.differ.diff(thi ...

Inserting a pause between a trio of separate phrases

I am dealing with three string variables that are stacked on top of each other without any spacing. Is there a way to add something similar to a tag in the ts file instead of the template? Alternatively, can I input multiple values into my angular compo ...

Incorporating @angular/fire into the latest version of Angular, version

I need help incorporating @angular/fire into my Angular 12 project for deployment on Firebase. After using the CLI to add @angular/fire, I ran the following command: ng add @angular/fire The output displayed was as follows: ℹ Using package manager: npm ...

Creating key elements in JavaScript with the push() function

I'm working on a basic shopping cart system using JavaScript (Ionic 2 / Angular). In my PHP code, I have the following: <?php $cart = array( 48131 => array( 'size' => 'STANDARD', 'qty' => ...

Issue: Unable to resolve all parameters for TypeDecorator in Angular 2 RC-6

I've been struggling with this error for more than a day, and I can't seem to figure out the cause. app.module import {NgModule} from "@angular/core"; import {BrowserModule} from "@angular/platform-browser"; import {AppComponent} from "./app.co ...

Pass a string with quotation marks to a component input in Angular 6

Need help with passing a string input to a component: @Component({ selector: 'abcComponent' template: ` <div> .... </div>` }) export class AbcComponent { @Input() text:string; } I am trying to send a strin ...

Calculate the sum of elements within an array

I've been attempting to calculate the sum of values in an array based on different levels, but so far I haven't had much success. Here are the data I'm working with (stored in a variable called totalByLevel): https://i.stack.imgur.com/rOP9 ...

Utilizing Angular for enhanced search functionality by sending multiple query parameters

I'm currently facing an issue with setting up a search functionality for the data obtained from an API. The data is being displayed in an Angular Material table, and I have 8 different inputs that serve as filters. Is there a way to add one or more s ...

Developing a calendar UI with similar features and functionality to Google Calendar using Ionic 2

My journey with Ionic 2 began only one week ago and has been relatively smooth sailing thus far. However, I have hit a roadblock - I need to create a calendar interface for users to book time slots. Can anyone offer assistance on how to tackle this task? ...