How can I use a deffered promise to call a method on the second controller from the first controller in AngularJS and Ionic?

I am facing a challenge where I need to initialize user setting values (which are set to rootscope) from the second controller's method in the first controller.

Once the values are successfully set to rootscope, I need to return a premise and continue executing the second method of the first controller.

I have tried using emit and broadcast examples, but haven't had any luck so far.

Can someone please provide advice on how to accomplish this correctly?

I'm working with Angular 1.2 and Ionic 1, beta 13

Thank you in advance for any assistance.

Template:

<ion-view title="{{ 'DAYS_RESULTS' | translate }}" >
    <ion-content ng-controller="DailyStatsCtrl" ng-init="setData()">

Code:

// First cotroller call setData in ng-init

angular.module('starter')
// Controller definition
.controller('DailyStatsCtrl', function($scope, $rootScope, $ionicSlideBoxDelegate, $timeout , $ionicLoading , $q, $translate, DialsComputeService, cordova, LocalStorService,  $ionicPopup, $state, $ionicNavBarDelegate, testService, $ionicPlatform) {


        $scope.setData = function() {
            $ionicPlatform.ready(function() {
                $timeout(function() {
                    $scope.$emit("onSomething", "");
                    alert("TEST");
                }, 1000);
            });
        }; 

In the second controller:

angular.module('starter')
// Controller definition
.controller('SettingsCtrl', function($scope, $rootScope, $ionicLoading, $ionicPlatform, LocalStorService, $timeout, $translate, $ionicPopup, $state, $ionicNavBarDelegate) {

    $scope.getUserSettigns = function() {
        alert("received");
        $scope.test = 'event received';
    }
    $scope.$on('onSomething', function(e) {
        $scope.getUserSettigns();
    });

Answer №1

When working with Ionic, it's important to note that a controller function cannot be called before the view of the controller has finished loading. If you need to ensure that your second controller's view has been loaded before executing a function, you can follow these steps:

secondview.html:

Assign an ID to the ion-content element in order to access the controller scope:

<ion-view title="second">
    <ion-content id="secondView">

    </ion-content>
</ion-view>

Second controller:

app.controller('SecondController', function($scope, $http) {

    $scope.someFunction = function(args) {
        alert(args.Message);
    };

});

Code:

app.controller('CodeController', function($scope) {

    $scope.$on('$ionicView.beforeEnter', function(){
        angular.element($('#secondView')).scope().someFunction({ Message: "Hello!" });
    });

});

I hope this explanation helps clarify any confusion.

Answer №2

To achieve the desired outcome, utilizing $rootScope is not necessary (though it can be used). The use of $broadcast will activate watchers for events in the current scope and all descendant scopes. For instance, the following code in the parent controller:

$scope.setData = function() {
    $timeout(function() {
      $scope.$broadcast("onSomething", "");
    }, 5000); 
  };

will invoke any defined $scope.$on('onSomething', ..) callbacks in both the current and descendant controllers.

For a demonstration with a live example, please refer to this CodePen link where the text 'event received' will be displayed after 5 seconds in the rendered HTML.

http://codepen.io/anon/pen/VYeEOg

Answer №3

Recently, I had the opportunity to dive into event emitting functionality within my code. It may seem like a hassle at first, but here's a brief overview:

$scope.$broadcast

This method is used to send events down to child scopes in the application.

According to the Angular documentation:

Dispatches an event name downwards to all child scopes (and their children)


$scope.$emit

On the other hand, this function sends events up to parent scopes.

As per the Angular documentation:

Dispatches an event name upwards through the scope hierarchy


My colleague and I strongly believe that using the $broadcast method is the most effective approach. To ensure reliability, we recommend injecting $rootScope in the controller or service responsible for dispatching the event and then using $broadcast as shown below:

.service('DispatchEvent', ['$rootScope', function ($rootScope) {
    $rootScope.$broadcast('someEvent');
}]);

For the controller or service handling the received event, inject $scope and employ $on as follows:

.controller('ReceivingEventsController', ['$scope', function ($scope) { 
     $scope.$on('someEvent', function (e) { 
         // do something 
     }); 
}]);

By following this approach, the $rootScope will consistently broadcast down the scope hierarchy, relieving the need to deliberate between $emit and $broadcast. Utilizing $scope ensures it will always be a child of $rootScope.


Applying this concept to your situation is straightforward. Inject $rootScope and utilize $broadcast in the first controller, while inject $scope and use $on in the second controller, similar to the example below:

$scope.$on('onSomething', function(e) {
    $scope.getUserSettings();
});

To see a demonstration, check out this functional plunker: http://plnkr.co/edit/PrD3vB80lFSt0a9WQLJ9?p=preview

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 the best way to dynamically insert a new row into a table, with each row containing a table heading and column?

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <table id="tbl" class="tbl1"> <tr> <th> mobileno </th> <td class='mo' id="mo_0"> </td> ...

Choosing a dynamic dropdown option using jQuery and AJAX

I am facing an issue with a select box that is dynamically populated and should display information about a single option. The problem I am encountering is that the browser does not trigger a ':selected' event when I click on any of the options. ...

reactjs implementation of a virtualized list

Recently, I stumbled upon the React-window library and found it to be incredibly useful. Intrigued by how it was built, I decided to try my hand at creating my own virtualized list. However, I encountered an issue where the list could only scroll up to it ...

Tips for updating comments using ajax technology

I need to implement AJAX in order to update the page automatically whenever a new comment is added, eliminating the need to manually refresh the page. I have attempted to achieve this by adding a section of code but it's not working as expected. Even ...

Unable to utilize $mdSelect within an AngularJS directive

I have been working on a solution to automatically close the md-select when an md-menu is closed. I have successfully implemented it in my code, which you can view here: https://codepen.io/anon/pen/jxXbrX. However, when trying to integrate this functional ...

What is the proper method for invoking object (class) methods from a router?

My apologies for the vague title. Let me clarify what I am attempting to accomplish. In this scenario, there are two main components: A class called 'wallet.js' A router named 'index.js' which handles GET requests This is my objectiv ...

Is there a way to access the rear camera on a mobile device using webcam.js?

Currently, I am utilizing webcam.js from the following link: https://github.com/jhuckaby/webcamjs. When accessing the website on mobile devices, the front camera tends to open by default. My objective is to switch this default setting to access the rear ...

Utilize the ng-controller directive with unique aliases across various sections of HTML code

I'm facing an issue with my ng-controllers when multiple controllers are used on the same page. For instance, I have one controller in the page header, another in a different section of the same page, and one in the content of the page. However, all o ...

Troubleshooting a Vue.js formatting problem in Visual Studio 2019

Encountering an issue with VS2019 while attempting to format this code section. <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="milestone.ascx.cs" Inherits="uc.dms.milestone" %> <section class="content-header"> <h1> ...

Having trouble with the Canvas Element in Three.js not displaying correctly? All I can see is a black

Hello everyone, I'm fairly new to utilizing three.js and I've been attempting to replicate a code snippet that I stumbled upon in an Observable notebook within a fiddle. If you're curious, here is the original code block: Despite my best ef ...

Deactivate a single choice within the select field while allowing the rest to remain active

I am facing a challenge where I have two select elements with the same options. My goal is to disable an option in one select element if it has already been selected in the other select element. Below are my two select elements: <select class="form-co ...

Interpolating backticks in Javascript allows for constructing a URL containing empty spaces

When utilizing string interpolation with backticks to construct a URL that sends data to a django endpoint, the resulting URL contains unnecessary whitespace and a new line. The problematic JavaScript code is as follows: (function (window, document, unde ...

Guide to exporting a JSON array asynchronously following an HTTP request in Node.js

I am facing a challenge with asynchronously exporting a variable. My goal is to access the apiData in another file. Currently, I am exporting an empty array for clear reasons. How can I achieve this asynchronously and retrieve the JSON data? var exp ...

Internet Explorer causing trouble with reliable Ajax dropdown selection

There are two drop-down lists on my website, where the options in one depend on the selection in the other. The Ajax code works perfectly fine in Chrome and Mozilla, but it's not functioning correctly in Internet Explorer (specifically IE9). I need so ...

What is the best way to retain multiple values passed through Output() and EventEmitter() in Angular?

In my Angular application, I have implemented custom outputs to transmit user-selected values between components. Currently, the functionality allows for the selected value from checkbox items to be sent to a sub-component, where it is displayed in the con ...

"Facing an issue with angular's $http post method as it fails to transmit

Attempting to use $http post in Angular to send an object to a REST service. The data is a JSON object that needs to be passed as a parameter for the method in the service. Here is my Angular code (which is not working for me): $http({ method:'P ...

Step-by-step guide to linking/referencing multiple scripts in an HTML file using React (no NODE.js required)

I'm currently working with React.js without Node.js, and I'm facing an issue linking multiple script files in my HTML file. Here is a snippet of my code: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> ...

Is it possible to utilize setTimeout to demonstrate the execution of a while loop visually?

I am working on a function that generates random numbers between 1 and 6 until it matches a target value of 3. I want to create a visual effect where each randomly generated number is displayed on the page, but I'm facing some challenges with delays. ...

The Art of Revealing an Element

Is it possible to manipulate a parent div element in JavaScript without affecting its child nodes? For example, transforming this structure: <div class="parent"> <div class="child"> <div class="grandchil ...

Tips for incorporating css @keyframes within a cshtml file:

My cshtml page includes a Popup that I created, but I encountered an issue with keyframes. When I tried to use it without keyframes, the fade effect was lost. I am looking for a way to fix my @keyframes. (I tested the code on Chrome and Opera) I found the ...