Is there a way to trigger a function in an AngularJS controller from a Backbone controller?

I've been working on an application that was originally developed using backbone and jQuery, but we had to incorporate new modules built with angular to meet client requirements. Routing in the application is handled by backbone route, and we have successfully integrated the angular modules.

However, I am facing a challenge where I need to access the current instance of a module in angular and execute a function from the controller of that module based on actions handled by a backbone controller.

Below is an example of how the angular module and controller are structured:

//chat.module.js
( function () {
angular
    .module( 'chat.module', [] );
})();

//chat.controller.js
(function () {
angular
        .module('chat.module')
        .controller('chat.controller', ['profileFactory', '$filter', '$q', '$timeout', 'Position', 'Chat', chat]);

function chat(profileFactory, $filter,  $q, $timeout, Position, Chat) {
    var vm = this;
    vm.initChatFlag = false;

    vm.initChat = initChat;
    vm.setInformation = setInformation;


    function setInformation() {
        //handle business logic here
    }

    ...

In backbone, the module can be created as shown below:

        chatmodule: function () {
        var self = this;
        var element = angular.element(document.querySelector('#modalCallback'));
        var chat = angular.element(document.querySelector('#chatModule'));
        var isInitializedChat = chat.injector();

        var isInitialized = element.injector();
        if (!isInitialized) {
            angular.bootstrap($('#modalCallback'), ['app']);
        }
        if (!isInitializedChat) {
            angular.bootstrap($('#chatModule'), ['app']);
        }

        //TODO: chat.controller.setInformation() get access to fields like chat.controller.initChatFlag etc

The main app module is defined as follows:

    (function(){
    angular
        .module('app',[
            'callback',
            'ui.bootstrap',
            '720kb.datepicker',
            'ngLocale',
            'directives.module',
            'interceptor',
            'directive.loading',
            'angularUtils.directives.dirPagination',
            'blog.module',
            'profile.module',
            'filters.module',
            'chat.module',
            'ui.toggle',
        ]);
})();

Answer №1

The AngularJS $injector plays a crucial role in performing magic within the codebase. By exposing it outside of AngularJS, you can connect it with non-AngularJS elements as demonstrated below:

//Defining a basic AngularJS service:
app.service('myService', function() {
  this.message = "This is my default message.";
});

//Making the injector accessible externally from the angular app.
app.run(function($injector, $window) {
  $window.angularInjector = $injector;
});

//Utilizing the injector to retrieve the service.
function nonAngularEventHandler() {
  angularInjector.invoke(function(myService, $rootScope) {    
    $rootScope.$apply(function() {
      myService.message = "Now this is my message."
    });
  });
}

Edit: Alternatively, simplify the process by following this approach.

//Instead of directly exposing the $injector, wrap it within a function
//that includes the $apply() functionality.
app.run(function($injector, $window, $rootScope) {

  $window.callInMyAngularApp = function(func) {
    $rootScope.$apply(function() {
      $injector.invoke(func);
    });
  }

});

//Call the function using an injectable function like shown below.
function nonAngularClick() {
  callInMyAngularApp(function(myService) {    
      myService.message = "Now this is my message."
  });
}

//For minification purposes, use the minify-safe version of the injectable function as depicted here
function nonAngularClick() {
  callInMyAngularApp(['myService', function(myService) {    
      myService.message = "Now this is my message."
  }]);
}

Update: (last one I promise!) While the previous methods work fine, it's recommended to expose a specific API instead of a generic injectable interface. Consider the following implementation.

//Introducing a limited API within a service
app.service("myExternalApi", function($rootScope, myService) {
  this.changeMyMessage = function(message) {
    $rootScope.$apply(function() {
      myService.message = message;
    });
  };
});

//Exposing the defined API
app.run(function($window, myExternalApi) {
  $window.myExternalApi = myExternalApi;
});

//Executing a cleaner external call from outside of angular.
function nonAngularClick() {
  myExternalApi.changeMyMessage("Now this is my message.");
}

Answer №2

I managed to gain entry into the controller by following the guidance provided in this post -

    var Chat = angular.element(document.querySelector('#chatModule')).scope();

    if(!Chat) return;

    if(Chat.chatCtrl.initChatFlag) {
        Chat.chatCtrl.setInformation();
    }else{
        console.log('Chat has not been initialized');
    }

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

I am encountering an issue with my ui-router resolve where it is not returning any information despite no

I am struggling to connect my MongoDb and API REST with my Angular application. It seems like there is an issue with resolution. Currently, I am following a MEAN application tutorial on this website. This snippet shows my ui-router configuration. var ap ...

Ways to simulate file operations in sinon?

I have a function that unzips a file from the directory, and it is working perfectly fine. index.js const unZip = async (zipFilePath, destDir) => { await util.promisify(fs.mkdir)(destDir); return new Promise((resolve, reject) => { fs.create ...

Hover over a ListItem

Looking for advice on how to incorporate a Mouseover feature into a Material UI ListItem from the following link: http://www.material-ui.com/#/components/list. As the "SecondaryText" is limited to 2 lines, I am exploring options to display additional data ...

Is there a way to transfer gulp.watch() to a pipe?

Currently, I have a basic task set up for linting changed JavaScript files: gulp.task('default', function() { // monitor JS file changes gulp.watch(base + 'javascripts/**/*.js', function() { gulp.run(&ap ...

Bootstrap Modal closing problem

While working on a bootstrap modal, I encountered an issue where the modal contains two buttons - one for printing the content and another for closing the modal. Here is the code snippet for the modal in my aspx page: <div class="modal fade" id="myMod ...

Tips for effectively managing loading state within redux toolkit crud operations

Seeking guidance on efficiently managing the loading state in redux-toolkit. Within my slice, I have functionalities to create a post, delete a post, and fetch all posts. It appears that each operation requires handling a loading state. For instance, disp ...

Troubleshooting responsive navigation bar in VueJs: Why are elements not appearing when ToggleButton is clicked?

I'm developing a VueJs single page application and I'm struggling to implement a responsive NavBar. No matter what I try, it just doesn't seem to work as expected. I've experimented with several solutions, and the closest I have come t ...

Can someone explain the inner workings of the Typescript property decorator?

I was recently exploring Typescript property decorators, and I encountered some unexpected behavior in the following code: function dec(hasRole: boolean) { return function (target: any, propertyName: string) { let val = target[propertyName]; ...

Exploring the combination of Babel and Next.js: Integrating custom scripts into a project

Hello, I am currently learning next.js and facing a common issue that I need help with. I have created my own ES6 JavaScript library and now I want to convert it to babel so I can use it in my next.js application. Is there a way to configure babel for sp ...

Refreshing a DIV in Rails by reloading from model using a JavaScript function

Recently, I created a page displaying the number of Widgets a customer has. Below is the view written in Haml: #available = "Available widgets: #{@customer.widgets.unused.count()}" (The "unused" scope in the model displays available widgets). When a C ...

What is the best method for concealing a specific element on the screen using ReactJS?

I'm looking for a way to have text displayed on the screen that is only hidden when a button is pressed, but I'm struggling to figure it out. I had the idea of using useState in this way: const [textVisibility, setTextVisibility] = useState(true) ...

Showing a gallery of images in React

I have a unique situation where I am working on setting a variable to match the import statement that calls for images. Once I have this variable assigned, I want to use it to display the corresponding image. For instance, if my code generates the name &ap ...

Decoding the values in an input field

Can anyone help me with identifying links, numbers, and text in WhatsApp and other app input boxes? I also want to be able to preview the page attached to a link and style these elements separately from other text. I am currently working on a project whe ...

What is the secret to creating a button that can sort text and another button that flips the word density in my content?

I'm not a fan of having something like this because it's displeasing to the eye: https://i.stack.imgur.com/3F4sp.jpg Instead, I prefer my word density to be more organized and structured. How can I achieve this? Sort by highest word density fi ...

Retrieving Data with Angular Http GET请求

When calling a service in Angular, I use the following code: return $http.get('api/properties', { params: { id: id } }); However, the resulting URL is: api/properties?id=2 This leads to an error because I actually need: api/properties/2 Wha ...

Angular 1: selecting all checkboxes within an extensive ng-repeat list

I am encountering a performance issue with a table that includes hundreds of rows, each containing a checkbox. When I use the "Check All" option at the top to select all checkboxes in one go, the browser becomes unresponsive, especially in IE11 which is th ...

Is it possible to incorporate numerous instances of SlickGrid by utilizing an angular directive?

Just started diving into AngularJS and it's been an exciting journey so far. I've come across the suggestion of wrapping external libraries into directories, which definitely seems like a good practice. While trying to create a 'slickgrid& ...

Tips on utilizing browser scroll for horizontal overflow of internal div?

I'm working on creating a dynamic page with a tree-like structure that easily exceeds the width of the browser window. My goal is to enable horizontal scrolling for the entire page using the browser's scrollbar, without needing a separate scrollb ...

Identifying the presence of an image in a directory and displaying a standard image if not found

I have a directory containing pictures of different wines, each labeled with a specific code (e.g. FMP-HTR17). I would like to show the corresponding picture if it is available, but display a default image if the specific picture does not exist in the dire ...

Adjusting the Transparency of the Background in a Pop-Up

I am experiencing an issue with my popup where I want the background to be transparent. However, when I set the opacity in CSS to 0.5 or less, the text also becomes transparent and very dark. How can I achieve a background with 50% opacity while keeping th ...