$scope.$on not triggering after $rootScope.$broadcast in angular service - javascript

This may be the repeated question but the workaround I found for this issue is not working in my case thats why I am posting the question.
I've following service:
appRoot.service('MyService', function($rootScope) {
var Messenger = {
Temp: "",
TempId:"",
tempMethod: function(Id) {
TempId = Id;
$rootScope.$broadcast('FirstCtrlMethod');
}
};
return Messenger ;
});
In second controller:
appRoot.controller('SecondCtrl', function ($scope, $location, MyResource, NotificationService, MyService) {
$scope.invokeFirstCtrl= function() {
var Id = '2';
MyService.tempMethod(Id);
});
In first controller:
appRoot.controller('FirstCtrl', function ($scope, $compile, $filter, $modal, $sce, $location, NotificationService, MyService) {
$scope.$on('FirstCtrlMethod', function () {
alert('I am from frist controller');
});
});
Problem: The line "$rootScope.$broadcast('FirstCtrlMethod');" is executing as expected but it is not causing to fire event "$scope.$on('FirstCtrlMethod', function () {.." in the first controller.
I've used the differenct services in many places in my app in the same way and they are workig fine, I am not understanding why it is not working here.

putting comment as an answer...
I guess the other controller which is supposed to receive the event is not yet instatiated when you are $broadcasting the event.
Please try instantiating the other controller

Please see below working example
var app = angular.module('app', []);
app.service('MyService', function($rootScope) {
var Messenger = {
Temp: "",
TempId: "",
tempMethod: function(Id) {
TempId = Id;
$rootScope.$broadcast('FirstCtrlMethod');
}
};
return Messenger;
});
app.controller('homeCtrl', function($scope, MyService) {
$scope.invokeFirstCtrl = function() {
var Id = '2';
MyService.tempMethod(Id);
};
});
app.controller('FirstCtrl', function($scope) {
$scope.$on('FirstCtrlMethod', function() {
alert('I am from frist controller');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="homeCtrl">
<button ng-click="invokeFirstCtrl()">Invoke</button>
</div>
<div ng-controller="FirstCtrl">
</div>
</div>

Related

Passing return of function to another state

I have been trying to send data from one controller to another. A little background this is code being used in an ionic application if that helps any. I want the to send the data from send() function to the SubCtrl. The send function is being called in MainCtrl. I have created a service for this but the data is still not being shared. What am I missing to complete this action?
var app = angular.module('testapp', []);
app.config(function($stateProvider, $urlRouterProvider) {
"use strict";
/* Set up the states for the application's different sections. */
$stateProvider
.state('page2', {
name: 'page2',
url: '/page2',
templateUrl: 'page2.html',
controller: 'MainCtrl'
})
.state('page3', {
name: 'page3',
url: '/page3',
templateUrl: 'page3.html',
controller: 'SubCtrl'
});
$urlRouterProvider.otherwise('/page2');
});
app.factory('dataShare', function($rootScope) {
var service = {};
service.data = false;
service.sendData = function(data) {
this.data = data;
$rootScope.$broadcast('data_shared');
console.log(data);
};
service.getData = function() {
return this.data;
};
return service;
});
app.controller('MainCtrl', function($scope, $state, $http, dataShare) {
$scope.text = 'food';
$scope.send = function() {
dataShare.sendData(this.text);
};
});
app.controller('SubCtrl', function($scope, $state, dataShare) {
"use strict";
var sc = this;
$scope.text = '';
$scope.$on('data_shared', function() {
var text = dataShare.getData();
sc.text = dataShare.data;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script id="page2.html" type="text/ng-template">
<div>{text}}</div>
<input type='text' ng-model='text' />
<button class="button button-outline button-royal" ng-click="send();">add</button>
</script>
<script id="page3.html" type="text/ng-template">
<div>text: {{text}}</div>
</script>
I was able to figure this issue out after reading this page. If anyone is having a similar issue I would encourage this reading. Also the video link on this post was really helpful.

Passing Parameter to Angular Factory from controller

I couldn't pass the parameter from angular controller to factory. Can any one help me on this? It works without passing parameter but when I pass it it's not.
var app = angular.module('employee', ['ui.grid', 'ui.grid.saveState', 'ui.grid.selection', 'ui.grid.cellNav', 'ui.grid.resizeColumns', 'ui.grid.moveColumns', 'ui.grid.pinning', 'ui.bootstrap', 'ui.grid.autoResize','ui.grid.pagination']);
app.controller('EmpCtrl', ['$scope', '$http', '$interval', '$modal', '$log', 'gridService', function ($scope, $http, $interval, $modal, $log, gridService) {
$scope.LoadNextPage = gridService.LoadNextPage("5");
}]);
var gridService = function ($http, $rootScope) {
return {
LoadNextPage: function (hh) {
alert(hh);
},
gridOptions:gridOptions
};
};
app.factory('gridService', ['$http', '$rootScope', gridService]);
And this is how I use it in the view
<span id="pcNext"
class="glyphicon glyphicon-step-forward"
ng-click="LoadNextPage()">
</span>
The problem is in your controller:
$scope.LoadNextPage = gridService.LoadNextPage("5");
This means that your LoadNextPage is not a function but rather a result of the call to a function in your service. Which btw doesn't return anything but rather just displays an alert. But in your view, you're using LoadNextPage as a function call...
Change it to this so your controller's LoadNextPage will be a function that you can call from the view.
$scope.LoadNextPage = gridService.LoadNextPage;
and in your view:
<span id="pcNext"
class="glyphicon glyphicon-step-forward"
ng-click="LoadNextPage(5)">
</span>
This should work.
Note: I suspect that your gridOptions are defined somewhere outside of scope of your code that you provided in the question so that it doesn't throw and error because of the missing (likely) object. So I considered this a typo in your code and not the actual problem.
Don't want params in your view?
No problem. You can either create a wrapper function or bind it to specific parameters in your code:
// wrap
$scope.LoadNextPage = function() {
return gridService.LoadNextPage("5");
};
// bind
$scope.LoadNextPage = gridService.LoadNextPage.bind(this, 5);
Or bake the number in your service...
Issue here is gridOptions:gridOptions is not defined which throws error.
Remove ,gridOptions:gridOptions from factory.
Check snippet for working code and compare with your code.
var app = angular.module('employee', []);
app.controller('EmpCtrl', ['$scope', 'gridService', function ($scope, gridService) {
$scope.clickMe = function() {
$scope.LoadNextPage = gridService.LoadNextPage("5");
}
}]);
var gridService = function() {
return {
LoadNextPage: function (hh) {
alert(hh);
}
};
};
app.factory('gridService', ['$http', '$rootScope', gridService]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="employee" ng-controller="EmpCtrl">
<button ng-click="clickMe()">Button</button>
</div>
you not defined gridOptions function see this link:
angular.module("myApp", []).controller("myCon", function($scope, $interval, gridService){
$scope.LoadNextPage = gridService.LoadNextPage("5");
}).factory('gridService', ['$http', '$rootScope', gridService]);
function gridService($http, $rootScope){
return {
LoadNextPage: function (hh) {
alert(hh);
}
};
}
see this link

Call function or pass data to another controller AngularJS

I already have seem other topics with this kind of issue, but no one could help me... So here is my issue:
I have a navbar with a button for search, this buttons makes and get request from a webservice and returns a json object which must be apply to fill an table list. The problem is, my button and my table are in separated controllers, and it does work like I expected.
var app = angular.module('clientRest', []).controller('lista', ['$scope', 'loadLista', function($scope, loadLista) {
$scope.contatos = loadLista.getContatos();
}]).controller('pesquisa', ['$scope', '$http', 'loadLista', function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato").success(function(response) {
loadLista.setContatos(response);
});
};
}]).service('loadLista', function() {
var contatos = [];
return {
getContatos: function() {
return contatos;
},
setContatos: function(c) {
contatos = c;
}
};
});
My code...
When I call listar() from pesquisa controller I need to send received data to $scope.contatos from lista controller to make my ng-repeat work, everything with a single click.
How can I do it?
Thanks everyone
Better to use a service to share data between two controllers / modules as this might be the best approach. You can refer the code segment given below to understand the concept.
angular.module('app.A', [])
.service('ServiceA', function() {
this.getValue = function() {
return this.myValue;
};
this.setValue = function(newValue) {
this.myValue = newValue;
}
});
angular.module('app.B', ['app.A'])
.service('ServiceB', function(ServiceA) {
this.getValue = function() {
return ServiceA.getValue();
};
this.setValue = function() {
ServiceA.setValue('New value');
}
});
In order to trigger the data receipt event, you may use
Broadcast / emit messages - with #broadcast / #emit
An angular promise with a call back
Controller initiation function to reload the previously read information from a service
.controller('MyController', function($scope, ServiceA) {
$scope.init = function() {
$scope.myValue = ServiceA.getValue();
};
// Call the function to initialize during Controller instantiation
$scope.init();
});
Use $rootScope.$emit to emit a change event when setting the variable and use $on to get the value in the lista controller. I used customListAr here just to demostrate a button click. Does this help?
var app = angular.module('clientRest', [])
.controller('lista', ['$scope', 'loadLista', '$rootScope',
function($scope, loadLista, $rootScope) {
console.log(loadLista);
$scope.contatos = loadLista.getContatos();
$rootScope.$on('change', function() {
$scope.contatos = loadLista.getContatos();
});
}
])
.controller('pesquisa', ['$scope', '$http', 'loadLista',
function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato").success(function(response) {
loadLista.setContatos(response);
});
};
$scope.customListAr = function() {
loadLista.setContatos(["item 1" , "item 2", "item 3"]);
}
}
])
.service('loadLista', ['$rootScope',
function($rootScope) {
var contatos = [];
return {
getContatos: function() {
return contatos;
},
setContatos: function(c) {
contatos = c;
$rootScope.$emit('change');
}
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="clientRest">
<div ng-controller="lista">
<ul>
<li ng-repeat="a in contatos">{{a}}</li>
</ul>
</div>
<div ng-controller="pesquisa">
<button ng-click="customListAr()">Click Me</button>
</div>
</div>
Your problem is that when you do $scope.contatos = loadLista.getContatos(); you are setting a static value, and angular is unable to effectively create a watcher for that object because your setContatos method is creating a new object each time. To get around this, have the controller's scope hold a reference to the parent object and then it will automatically have a watcher on that object.
var app = angular.module('clientRest', [])
.controller('lista', ['$scope', 'loadLista', function($scope, loadLista) {
$scope.contatos = loadLista.contatos;
}])
.controller('pesquisa', ['$scope', '$http', 'loadLista', function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato"
).success(function (response) {
loadLista.contatos.data = response;
});
};
}])
.service('loadLista', function() {
var lista = {
contatos: {},
};
return lista;
});
// view:
<ul>
<li ng-repeat="contato in contatos.data">
{{ contato }}
</li>
</ul>

Injection error, using ui-bootstrap

Unknown provider: $confirmModalProvider <- $confirmModal <- confirmModalCtrl
Why am I getting this error? I'm trying to use AngularJS UI Bootstrap to open a modal and get the result. I get this error when I trigger $scope.deleteQuestion(). Any idea what I'd doing wrong here?
var crtPromoCtrl = angular.module('crtPromoCtrl', ['crtPromoSrv']);
crtPromoCtrl.controller('surveyCtrl', ['$scope', '$modal', 'surveySrv', function($scope, $modal, surveySrv)
{
$scope.questions = surveySrv.getQuestions();
$scope.editQuestion = function(index)
{
surveySrv.setEditQuestion(index);
};
$scope.deleteQuestion = function(index)
{
var confirmModal = $modal.open({
templateUrl: 'confirm-delete.html',
controller: 'confirmModalCtrl',
size: 'sm'
});
confirmModal.result.then(function(msg)
{
console.log(msg);
});
return false;
};
}]);
crtPromoCtrl.controller('confirmModalCtrl', ['$scope', '$confirmModal', function($scope, $confirmModal)
{
$scope.yes = function()
{
$confirmModal.close('yes');
};
$scope.no = function()
{
$confirmModal.dismiss('no');
};
}]);
EDIT: https://angular-ui.github.io/bootstrap/#/modal
You second controller should use $modalInstance instead of $confirmModal
Please note that $modalInstance represents a modal window (instance)
dependency.
Code
crtPromoCtrl.controller('confirmModalCtrl', ['$scope', '$modalInstance', function($scope, $modalInstance) {
$scope.yes = function() {
$modalInstance.close('yes');
};
$scope.no = function() {
$modalInstance.dismiss('no');
};
}]);

Angular.js | Sharing a ngModel

So, this is my HTML.
<input type="text" id="ghusername" ng-model="username" placeholder="Github username...">
<span id="ghsubmitbtn" ng-click="getUsers()">Pull User Data</span>
This is my Controller A.
app.controller("homeController", ["$scope", "$http", function ($scope, $http) {
$scope.getUsers = function () {
$http.get("https://api.github.com/users/" + $scope.username)
.success(function (data) {
//some stuff
})
And this is B (for posting sake). How do I get this username on the HTML ngModel, so that I can show it in another controller? ex:
app.controller("reposController", ["$scope", "$http", function ($scope, $http) {
$scope.getRepos = function () {
$http.get("https://api.github.com/users/" + $scope.username + "/repos")
.success(function (data) {
// some stuff
})
};
I've tried to user services, factories and even $rootScopes, but they just don't seem to work, any help? Btw, if I wasn't clear tell me and I will edit the post, Thank you.
EDIT: I ended up using $rootScope, I know it isn't the best idea but it was a minor thing. I'll keep all your answers for reference tho, as I'm sure they all work but I'm just too dumb to implement them.. Thank you.
You must to refernce $rootScope into your controllers:
app.controller("homeController", ["$scope", "$http","$rootScope", function ($scope, $http, $rootScope) ...
and after that just access rootscope variables:
controller1: $rootScope.someValue = "some value";
Controller2: $scope.controllerScopeValue = $rootScope.someValue;
Use service
app.service('name', [function(){}])
Then add 'name' to both the controllers like
app.controller("reposController", ["$scope", "$http", 'name', function ($scope, $http, name) {
$scope.name = name;
Then you can access it like
name.username
and in html
<input type="text" id="ghusername" ng-model="name.username" placeholder="Github username...">
Try something like this
http://jsfiddle.net/devkickstart/nevyhdn0/2/
Using a factory you can share the data between controller like so...
<div ng-app="myApp">
<div data-ng-controller="reposCtrl">
<input type="text" id="ghusername" ng-model="username" placeholder="Github username..." ng-init="getRepos()" />
{{data}}
</div>
<div data-ng-controller="homeCtrl"> <span id="ghsubmitbtn" ng-click="getUsers()">Pull User Data</span>
{{otherData}}
</div>
</div>
angular.module("myApp", [])
.factory("dataFact", ["$rootScope", function ($rootScope) {
var myData = "value from factory";
return {
getData: function () {
return myData;
},
setData: function (newVal) {
this.myData = newVal;
}
}
}]).controller("homeCtrl", ["$scope", "dataFact", function ($scope, dataFact) {
$scope.getUsers = function () {
$scope.otherData = dataFact.getData();
}
}]).controller("reposCtrl", ["$scope", "dataFact", function ($scope, dataFact) {
$scope.getRepos = function () {
$scope.username = dataFact.getData();
}
}]);
With some assumptions about your data model, this should work.
It creates a shared singleton object. One controller adds the user (or whatever data) as an attribute of that. Then other controllers, or indeed the same controller if it is reloaded, can then access the same data on shared.
Note here that a service just returns a singleton of anything, it doesn't need code or methods. In this case, it's easier to use a value instead which is shorthand for function() { return {}; } and works just as well.
Remember to inject shared wherever it is needed.
app.controller("homeController", ["$scope", "$http", "shared", function ($scope, $http, shared) {
$scope.getUsers = function () {
$http.get("https://api.github.com/users/" + $scope.username)
.success(function (data) {
shared.user = data.user; // or wherever it comes from
//some stuff
})
app.controller("reposController", ["$scope", "$http", "shared", function ($scope, $http, shared) {
$scope.getRepos = function () {
$http.get("https://api.github.com/users/" + shared.user.name + "/repos")
.success(function (data) {
// some stuff
})
};
app.value('shared', {});

Categories

Resources