Having trouble with the removeEventListener OnDestroy not functioning properly in Angular 6 using Javascript?

I have been experimenting with using the removeEventListener function in my Angular component. I came across a helpful discussion on this topic: Javascript removeEventListener not working

    ...
    ngOnInit() {
        document.addEventListener('visibilitychange', () =>this.handleVisibleState(), true);
    }

    ngOnDestroy() {
        document.removeEventListener('visibilitychange', () => this.handleVisibleState(), true);
    }

    handleVisibleState() {
        let vis = document.visibilityState === 'visible';
        this.configsService.update_collab_visible(vis);
    }
    ...

The issue I encountered is that the addEventListener continues to work even after ngOnDestroy() is called.

Can anyone provide guidance on how to properly unbind visibilityState from the document within Angular components?

attempt 2

    private visibilityChangeCallback: () => void;

    ngOnInit() {
        this.visibilityChangeCallback = () => this.handleVisibleState();
        document.addEventListener('visibilitychange', this.handleVisibleState, true);
    }

    ngOnDestroy() {
        document.removeEventListener('visibilitychange', this.handleVisibleState, true);
    }

    handleVisibleState() {
        let vis = document.visibilityState === 'visible';
        console.log(typeof this.configsService); // undefined
        this.configsService.update_collab_visible(vis);
    }

After implementing these changes, I encountered the following error:

ERROR TypeError: Cannot read property 'update_collab_visible' of undefined

Answer №1

Save the callback for later:

private storeVisibilityCallback: () => void;

ngOnInit() {
    this.storeVisibilityCallback = () => this.handleVisibleState();
    document.addEventListener('visibilitychange', this.storeVisibilityCallback, true);
}

ngOnDestroy() {
    document.removeEventListener('visibilitychange', this.storeVisibilityCallback, true);
}

Answer №2

When you call the removeEventListener() function with arguments that do not match any currently registered EventListener on the EventTarget, it will have no effect. Make sure you are passing the correct function.

One way to ensure success is by using an instance arrow function:

ngOnInit() {
    document.addEventListener('visibilitychange', this.handleVisibleState, true);
}

ngOnDestroy() {
    document.removeEventListener('visibilitychange', this.handleVisibleState, true);
}

handleVisibleState = () => {
    let vis = document.visibilityState === 'visible';
    this.configsService.update_collab_visible(vis);
}

Answer №3

To ensure consistency in the function reference, it is recommended to make the function a property field on the class using an arrow function rather than an anonymous function.

The error message

Cannot read property 'update_collab_visible' of undefined
occurs when a class function is used instead of a class field, causing the this context to be misplaced within the function:

ngOnInit() {
    document.addEventListener('visibilitychange', this.handleVisibleState, true);
}

ngOnDestroy() {
    document.removeEventListener('visibilitychange', this.handleVisibleState, true);
}

handleVisibleState = () => {
    let vis = document.visibilityState === 'visible';
    this.configsService.update_collab_visible(vis);
};

Alternatively, consider utilizing other methods such as incorporating rxjs library for better event handling:

destroy = new Subject<void>();

ngOnInit() {
  fromEvent(document, 'visibilitychange', true).pipe(
    takeUntil(this.destroy)
  ).subscribe((event) => this.handleVisibleState(event));
}

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

sponsored content

If you are interested in enhancing template and component event binding with additional features, check out the ng-event-options angular library:

@HostListener('document:visibilitystate.c')
handleVisibleState() {
    let vis = document.visibilityState === 'visible';
    this.configsService.update_collab_visible(vis);
}

Implementing this solution will address the issue at hand.

Answer №4

The explanation for why this.<anything> fails to function is due to the fact that the context of this changes when it's inside a callback and not properly bound.

By utilizing bind on this, the issue can be resolved.

document.addEventListener('visibilitychange', this.handleVisibleState.bind(this), true);

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

Starting object arrays in Angular 6 using ES6

As someone who is just starting out with javascript, I have encountered a challenge with a nested class structure. Specifically, I am looking to initialize an array of EventDate objects and assign it to 'this.dates' within the CustomerEvents cons ...

The element event does not trigger an update on the view

I am trying to display the caret position of my editor on a specific place on the website. I have created a directive and service to share variables between the controller and directive. Inside the directive, I have enabled events like "keyup", "mouseup", ...

Utilizing checkboxes for toggling the visibility of buttons in Angular

I want to dynamically show or hide buttons based on a checkbox. Here is the HTML code I am using: <input class="form-check-input" [(ngModel)]="switchCase" type="checkbox" id="flexSwitchCheckChecked" (change)=" ...

Unable to utilize material tabs in this situation

Discovering the material tabs feature at https://material.angular.io/components/tabs/api#MatTab got me excited to implement it in my project. After adding the suggested import, I encountered an issue where I couldn't find the module "@angular/materia ...

How come I can click on both radio buttons simultaneously?

How come I can select both radio buttons simultaneously? <form #form="ngForm"> {{ poll.counter1 }} votes <input type="radio" id="{{ poll.choice1 }}" value="{{ poll.choice1 }}" (click)="onChoice1(form)">{{ poll.choice1 }} <br> ...

Encountered 'DatePickerProps<unknown>' error while attempting to develop a custom component using Material-UI and react-hook-form

Currently, I'm attempting to create a reusable component using MUI Datepicker and React Hook Form However, the parent component is throwing an error Type '{ control: Control<FieldValues, object>; name: string; }' is missing the follow ...

Utilizing Input Data from One Component in Another - Angular4

As a newcomer to Angular, I'm facing an issue where I need to access a variable from ComponentA in ComponentB. Here's the code snippet that demonstrates what I'm trying to achieve (I want to utilize the "favoriteSeason" input result in the " ...

Sending an array of functions to the onClick event of a button

Having difficulty with TypeScript/JavaScript Currently working with an array of functions like this private listeners: ((name: string) => void)[] = []; Successfully adding functions to the array within another function. Now looking to trigger those ...

An error is triggered by the EyeDropper API stating that 'EyeDropper' has not been defined

I am trying to utilize EyeDropper for an eyedropper function in my project that uses Vue2 + Ts. Here is the code snippet: <div v-if="haveEyeDropper" @click="handleClickPick" > <i class="iconfont icon-xiguan"> ...

Guidelines on incorporating emotion/styled into React applications with TypeScript

Including my root component in the ThemeProvider from @emotion/react has granted me access to props.theme. Here is an example: const StyledDiv = styled.div` background-color: ${(props) => props.theme.palette.primary.main}; `; Issue: TypeScript indica ...

Guide to Conditionally Importing a Module in Angular

I am currently developing a module for Search integration. Instead of directly importing the SearchModule inside my app.module.ts file, I would like to implement a method where an API is called and the SearchModule is imported based on the API response. @N ...

Creating Instances of Parameterized Types

Consider the following scenario: class Datum {} An error message (error TS2304: Cannot find name 'T') is encountered when attempting the following: class Data<T extends Datum> { datum: T constructor() { this.datum = new ...

Is it possible for an ngrx effect to trigger the same action more than once?

I am working with an ngrx effect that needs to trigger multiple calls to the same ngrx action with different parameters. Here is my current approach: @Effect({dispatch: true}) public handleNodeWillReceiveFocus$ = this.actions$ .pipe( ofType( ...

"Linking a Next.js application with Azure's Application Insights for advanced insights

Trying to include my Next.js (TypeScript) app logs in Azure Application Insights has been a bit challenging. The documentation provided poor guidance, so I decided to follow this solution: https://medium.com/@nirbhayluthra/integrating-azure-application-ins ...

Requesting Next Page via Angular GET Method for Paginated API

Having trouble loading data from a paginated REST API using the code below. Any suggestions for a better approach are welcome! component.ts import { Component, OnInit } from '@angular/core'; import {HttpClient} from '@angular/common/http&a ...

The design of Angular Material's <mat-table> does not render properly when using the window.print() function

I am currently using Angular material 6 to present data in a grid format utilizing material components. When it comes to printing, I have a "printReport()" function that captures the HTML content from the view and triggers the window.print() method. The i ...

Tips for limiting users to inputting only alphanumeric characters and excluding special characters in an input field using Angular 8

How can I prevent users from inputting special characters in an input field and only allow alphanumeric values? The code that I have implemented so far does not seem to be working as intended. When a user enters a special character, it still shows up in th ...

Tips for parsing text responses in React to generate hyperlinks and emphasize specific words

I'm currently tackling a React project and facing an interesting challenge. I have a text response that needs to be parsed in a way that all URLs are automatically turned into clickable hyperlinks (using anchor tags). Moreover, there's a requirem ...

Default Angular2 route component for the RC5 program

My PHP website already in place, and I started integrating Angular2 components into it. I've implemented a router script to handle loading different components based on the URL. However, upon navigating away from a component page, I encounter the fol ...

Leveraging the TypeScript definitions for express-validator

I've been working on converting my code to TypeScript, but I'm running into issues with express-validator definitions. Here's a snippet of my code: ///<reference path='../../../d.ts/node.d.ts' /> ///<reference path=&apos ...