AngularJS directive $destroy is a useful tool for managing the

My angular application has been configured with the use of ng-view. Within one specific view, there is a dynamically loaded component alongside the view itself. This component acts as a directive that compiles its contents to allow for further interaction with other directives. The content within this component is compiled using

$compile(element.contents())(scope);
.

For example:

<ng-view>
  <viewer doc="getDocument()">
  </viewer>
</ng-view>
angular.directive('viewer', ['$compile', '$anchorScroll', function($compile, $anchorScroll) {
  return function(scope, element, attrs) {
    scope.$watch(
      function(scope) {
        var doc = scope.$eval(attrs.doc);
        if (!doc)
          return ""
        return doc.html;
      },
      function(value) {
        element.html(value);
        $compile(element.contents())(scope);
      }
    );
  };
}]);

The issue I am facing arises when switching routes, causing a switch in the content of either ng-view or viewer. This problem leads to a memory leak, where certain directives within the viewer continue to hold onto events and do not clean up properly upon route change.

An example of such a directive is shown below:

angular.directive('i18n', ['$rootScope', 'LocaleService', function($rootScope, LocaleService) {
  var cleanup;
  return {
    restrict: 'EAC',
    compile: function(element, attrs) {
      var originalText = element.text();
      element.text(LocaleService.getTranslation(originalText, attrs.locale));
      cleanup = $rootScope.$on('locale-changed', function(locale) {
        element.text(LocaleService.getTranslation(originalText, attrs.locale || locale));
      });
    },
    link: function(scope) {
      scope.$on('$destroy', function() {
        console.log("destroy");
        cleanup();
      });
    }
  };
}]);

What steps can be taken to ensure these events are properly cleaned up?

Answer №1

Your i18n example is effective if used sparingly.

It's recommended to avoid event binding within the compile function and instead use the link function as shown here:

angular.directive('i18n', ['$rootScope', 'LocaleService', function($rootScope, LocaleService) {
  return {
    restrict: 'EAC',
    link: function(scope, element, attrs) {
      var cleanup;
      var originalText = element.text();
      element.text(LocaleService.getTranslation(originalText, attrs.locale));
      cleanup = $rootScope.$on('locale-changed', function(locale) {
        element.text(LocaleService.getTranslation(originalText, attrs.locale || locale));
      });
      scope.$on('$destroy', function() {
        console.log("destroy");
        cleanup();
      });
    }
  };
}]);

Another approach is to bind the event on the child scope and utilize $broadcast on $rootScope for triggering, ensuring automatic garbage collection upon scope destruction:

angular.directive('i18n', ['$rootScope', 'LocaleService', function($rootScope, LocaleService) {
  return {
    restrict: 'EAC',
    link: function(scope, element, attrs) {
      var originalText = element.text();
      setElText();
      function setElText(locale){
        element.text(LocaleService.getTranslation(originalText, attrs.locale || locale));
      }
      scope.$on('locale-changed', setElText);
    }
  };
}]);

$rootScope.$broadcast('locale-change', 'en-AU');

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 causing the counter to appear twice in the console with varying values?

Recently, I was exploring the React 'ref' feature and decided to experiment with the code snippet below. import { useEffect } from "react"; import { useRef } from "react"; import { useState } from "react"; const But ...

Using JQuery to parse an XML file and automatically redirecting the page if a specific attribute equals "Update"

Updated I've made some edits to clarify my request. My website is built using HTML5, CSS3, and JQuery, resulting in all content being on one page. During updates, I want the ability to set an option in a configuration file so that when users visit m ...

Enhance Your Website with HTML and JavaScript

Here is the code snippet I am working with: sTAT **javascript** var acc = document.getElementsByClassName("item-wrapper"); var i; for (i = 0; i < acc.length; i++) { acc[i].onclick = function(){ this.classList.toggle("selected"); this.nextElementS ...

Best practices for displaying a Multidimensional JSON Object using JavaScript

Within my current project, I have a JSON object structured as follows: { "face": [ { "attribute": { "age": { "range": 5, "value": 35 }, "gender": { "confidence ...

When attempting to declare a functional component in React utilizing styled-components in TypeScript, an error is encountered stating "No overload matches this call."

Playground https://codesandbox.io/s/typescript-type-checking-question-0b42t Sample Code type BadgeTypes = { success: string; secondary: string; alert: string; text: string; }; type Theme = { fonts?: object; borderRadius: string; primary?: o ...

Finding the minimum value in a list and the maximum value in JavaScript

My current JavaScript list consists of dollar coin values: let x = [1.0, 2.5, 5.0, 20.0, 50.0, 100.0, 500.0, 2000.0, 5000.0] My challenge is finding an equation in JavaScript that will allow me to use the smallest number of coins to reach the desired max ...

What is the functionality of Mongoose for handling multiple updates?

Array; arr=[ { id: [ '5e6e9b0668fcbc7bce2097ac', '5e6e9b0e68fcbc7bce2097af' ], color: [ 'a', 'b' ] } ] Models; const varyant = Models.varyant function; Promise.all( arr.map((item)=>{ return var ...

Using Angular 2 HTTP to retrieve a list of file names from a Node backend directory

I am currently attempting to establish a connection between an Angular 2 frontend and a Node/Express backend using an HTTP GET request. The backend should respond by providing a list of file names from a specific folder using the fs.readdir method. I have ...

Prevent clicking on a specific column in a table using Jquery

Attempting to utilize Jquery for clicking on a table row in order to navigate to a new page. However, encountering an issue with the last column containing a button that redirects to a new page when clicked on the edge. Is there a way to disable the oncl ...

Getting an error in AngularJS with $http.get: "TypeError: boolean is not a function"

I've implemented angularjs $http.get in a factory to make an API call. When I ran my angularjs application, it successfully returned the data. However, upon inspecting the console using F12, I encountered the following error: "TypeError: boolean is n ...

Injection of Angular state resolve into controller fails to occur

I'm attempting to ensure that the value from ui-router's resolve is successfully passed to the controller portalsForUserCtrl. Take a look at the router code below: (function () { 'use strict'; var myApp = angular.module("myApp", ["co ...

Issue with ng-click not triggering the $mdDialog callback

Utilizing Angular Material, I have functionality in TasksCtrl that triggers a $mdDialog - utilizing the locals property to pass an object that will be changed in DialogCtrl before being returned to the view. Nevertheless, the .then() callbacks do not trig ...

What strategies can be implemented to improve the total blocking time in Vue for optimal performance

I'm facing a challenge that I can't seem to resolve. My page has a high total blocking time (2+ sec). Despite trying to load every vue component asynchronously, the issue persists with 2+ sec TBT. I'm puzzled by what could be causing such a ...

When encountering [Error in render: "TypeError: Cannot read property 'length' of undefined"] across various files, what could be causing it to appear in more than one instance?

Currently, I am engrossed in a Vue tutorial centered around creating a basic email application. However, during my test run, the inbox's content failed to display as expected (referencing the images attached below). The first image depicts my version, ...

"Exploring the dynamic features of jQuery's mobile listview and

As I work on creating a mobile app using jQuery Mobile, I find myself facing some challenges. Despite my efforts and attempts at different methods, I have not been successful in achieving the desired functionality. Specifically, I am trying to implement a ...

After the ajax request is made in React JS, the column vanishes from the screen

Upon querying a node.js server's PostgreSQL database, I receive specific data that needs to be displayed in two separate tables. Each table consists of two columns. However, after the AJAX call, only the first column is being populated in the first ta ...

Is it possible to create a return type structure in TypeScript that is determined by the function's argument?

I'm currently stuck on developing a function that takes a string as an argument and outputs an object with this string as a key. For example (using pseudo code): test('bar') => {bar: ...} I am facing difficulties in ensuring the correct ...

Utilize Angular2 with ES6 modules while running an Express server

Having some issues using ES6 Modules with Angular2 in an app served by Node.js and Express.js. When attempting to load the Angular2/ES6 app in browser, encountered this error message in the FireFox console: The stylesheet http://localhost:8080/boot.css w ...

"Exploring the Mini Drawer feature on Material UI brings up a whole new page for the Link

Currently, I am working on a project that involves updating stocks using Material UI. I have implemented a mini drawer from Material UI, but when I click on the menu link, it routes to a new page instead of rendering on the homepage itself. In my App.JS f ...

What is the method for locating an element within an array?

The content being returned is presenting a challenge. How can I retrieve data from inside 0? I attempted to access it using date[0] without success const { data } = getData(); The result of console.log(data) is shown below: enter image description here ...