The JavaScript function is being triggered multiple times by the event listener, even though I explicitly reference the function

Every time I create an angular controller, I add an event listener. However, when I return to the page after leaving it, a new event listener is added because the constructor is called again.

Unfortunately, when this event is triggered, it gets invoked multiple times - twice, thrice, and so on as I keep leaving and coming back. My intention is for it to be invoked only once.

Below is the code snippet where I add the event listener along with the function it calls: (For your information, I am using TypeScript)

In Constructor:

this.$window.addEventListener("message", this.processApi, false);

Function Called:

processApi = (e) => {
    this.processApiMessage(e.data);
};

I've come across suggestions to use a reference to a function rather than writing it out directly to ensure that both refer to the same instance of a function. However, even with this approach, the same event listener is being called multiple times.

Upon inspecting Chrome's Developer Tools and navigating to Event Listeners, specifically the message section, I notice a new Window element every time the constructor is executed. While I can manually remove each Event Listener via developer tools, I encounter issues doing so in the code by calling:

this.$window.removeEventListener("message", this.processApi, false);

Refreshing the page clears all event listeners and recreates the one in the constructor, which resolves the issue temporarily.

Within my angular setup, I initially used the $location service to navigate to the URL linked to my controller. As a quick fix to ensure that the event listener is hit only once, I replaced $location.url("url") with window.location.href("url"). This method seems effective as the page refreshes upon navigation. However, I prefer sticking to utilizing the $location service for routing while ensuring that my event listener is triggered just once despite the repeated invocation of the angular constructor.

Answer №1

In order to properly manage event listeners, it is essential to remove them when the scope is destroyed. To achieve this, you can inject the $scope object in the controller constructor and implement the following code snippet:

$scope.$on('$destroy', () => 
  $window.removeEventListener("message", this.processApi));

There are several ways to create a controller, but one common approach (especially in TypeScript) is to define a class for the controller.

For better Angular convention, consider adding the listener to the rootScope instead of directly to $window. Combining all these suggestions, your code could look like this:

class MyController {
  constructor($rootScope, $scope) {
    'ngInject';

    let unsubscriber = $rootScope.$on('message', this.processApi, false);    
    $scope.$on('$destroy', () => unsubscriber());  
  }
  ...
}

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

Encounter an error parsing the package.json file. Confirmed that it is valid JSON

As I embark on creating my very first yeoman generator, I have encountered an issue when running yo to initiate the project. The error message I am receiving is as follows: npm ERR! install Couldn't read dependencies npm ERR! Darwin 14.0.0 npm ERR! a ...

Version 1.4 of Angular, Spring Security with POST method and Cross-Origin Resource Sharing (

After successfully sending a JSON with a list from Angular to Spring MVC using the POST method, I encountered an issue with Spring Security. When attempting to use Spring security, I faced Error 401 as the POST request was transformed into an OPTIONS reque ...

Once the data in the React context has been updated, the next step is to trigger a re-render of the

In my React application, I have implemented a system where certain components will display based on whether the user is logged in or not. To ensure this state is shared throughout the entire application, I created a context file called AuthProvider: import ...

Changing the location of an ArcGIS map with a click event in a Vue application

I am attempting to dynamically update a map to display my current location using Vue. I have created an onClick event that updates the props and sends them to my map component. To trigger a re-render of the map component when the data changes, I am utilizi ...

Is it possible to utilize a function within an Angular [routerLink] to define the query parameter?

When receiving a response from the API without an ID, it presents data fields like url, name, gender, culture, etc. However, I need to create a route to access specific character information using /characters/:id. Since there is no direct ID provided in th ...

Problem with jQuery's .prepend method being called twice on list items

Looking to enhance the appearance of a list by adding some icons before the anchor links within each list item. <ul class="submenu-children"> <li><a href="#">Link</a></li> <li><a href="#">Link</a></li> ...

Utilizing arrays to populate a line graph in Highcharts

I am struggling to figure out how to incorporate data from an array obtained from another function in my javascript file into my line graph. I want to confirm that this is feasible without switching to a different graphing package. Below is my current co ...

Bringing joy to a JS library: Embracing both Node and the Window

I have developed a JS library that I want to convert into a Node module for use with Node.js. This library extends the Canvas context API and relies on the use of getImageData(). Therefore, it begins with a defensive check to ensure compatibility: if (wi ...

Can someone explain the meaning of this code?

Recently, I came across a project where this line of code was used in a jQuery script. I'm not sure of its purpose and would appreciate some help understanding why it was included. If necessary, I can provide the entire function for reference. $("#ta ...

Sending the selected option from a dropdown menu to populate a textbox on a separate webpage using PHP, jQuery, and AJAX

I am looking to dynamically update the value of a dropdown in index.php to a textbox in test.php using Ajax. The scenario involves having test.php embedded as an iframe within index.php. Upon changing the dropdown selection, the corresponding value should ...

Implementing a DataTable filter functionality using external buttons or links

I want to enhance the search functionality of my table by incorporating a treeview style set of buttons or links next to it. This is how I envision it: Take a look at this design: https://i.sstatic.net/LAJXf.png Here's where it gets tricky. When I c ...

The custom error page in NextJS is failing to display

In my custom pages/404.ts file, I have coded the following: export default function NotFound() { return <h1>404 - Page Not Found</h1> } Additionally, there is another page that displays a 404 error when the organization is null: import Error ...

TypeScript feature: Determining return type dynamically based on object property using string literal

I am looking to enhance the functionality to dynamically determine the return type based on the string literal provided. Current Approach: type Baseball = { name: string; lng: number; lat: number; } type SeriesInfo = { series: { [key: string]: ...

Implementing Dynamic Script Injection in Angular Controllers for Enhanced HTML Functionality

I'm a total beginner when it comes to Angular and frontend development, so please bear with me if my question seems basic: In my controller, I have the following code where I am populating the $window.user data that is being used in the script [2] ad ...

Tips for resetting and configuring timer feature?

A feature in my quiz app requires setting up a timer in the controller that counts for 30 seconds and stops the quiz if there is no activity within that time frame. The timer should reset and start counting again if there is any activity. I have implemente ...

Creating an HTML table dynamically through JavaScript within a script block

I am working on using a JavaScript API to send emails, with the ability to include HTML. I am trying to create a table inside the email body, but it doesn't seem to be displaying properly. Here is the code snippet I'm using: <script> $ ...

What steps do I need to take to adjust this function based on the timezone?

Is there a way to retrieve the current time based on a specific timezone of my choice? let getCurrentTime = () => { var today = new Date(); var hh = String(today.getHours()) var mm = String(today.getMinutes()) //January is 0! var ss = ...

Looping through a large object array in the back-end using observables with RxJS

I have developed a basic number array and utilized rxjs for managing UI and the backend loop. Below is my code snippet: const array100 = new Array(9703) .fill('x') .map((value, index) => index); Rx.Observable.from(array100) .delayWhen ...

Dispose the inputpicker filter after setting the value

I am currently utilizing the "Jquery inputpicker plugin" for creating dropdown menus. More information about this plugin can be found here. To initialize my dropdown, I use the following code: $('#test').inputpicker({ data:[ {value:"1 ...

Using the GUI builder in Google App Script to include list box elements

Just starting out with javaScript and could use some guidance on using App Script. I've inserted a list box called "List Stocks" in GUI Builder, alongside a function named "listStockQuotes()" in Events. However, I'm unsure of how to add elements ...