Angularjs how to call a function of a controller from another controller - javascript

I am trying to split a big controller. The way to go would be through factories, but since I am changing the DOM I should do it through controllers.
Then, what I am trying to achieve is to call a function defined in Cntrl2 from Cntrl1.
The example
html
<body ng-app="app">
<div ng-controller='Cntrl1'>
{{message}}
</div>
</body>
js
var myModule = angular.module('app', []);
angular.module('app').controller('Cntrl1',
['$scope', '$q', '$timeout', 'Share_scope',
function ($scope, $q, $timeout, Share_scope) {
Share_scope.process();
$scope.message = 'started';
}]);
angular.module('app').controller('Cntrl2',
['$scope', '$q', '$timeout', 'Share_scope',
function ($scope, $q, $timeout, Share_scope) {
Share_scope.x = function() {
alert('done');
}
}]);
angular.module('app').factory('Share_scope',
['$window', '$q',
function($window, $q) {
var x;
return {
process: function() {
return x;
},
};
}]);
The demo http://jsfiddle.net/T8rgv/7/
What I would expect is to define "var x" of the factory as the function of Cntrl2, and then execute this function through the factory when I call it from Cntrl1.
So, how to make this work? Is this approach correct? Or should I just change the DOM from a factory?
Cheers,
Gerard

Not knowing where in relation Cntrl2 is to Cntrl1, I would use emit or broadcast somewhat like this. Note from past experience I don't think it's a good idea to use two or more different modules in the same page.
var myModule = angular.module('app', []);
angular.module('app').controller('Cntrl1',
['$scope', '$q', '$timeout', 'myFactory',
function ($scope, $q, $timeout, myFactory) {
$scope.$emit('messageEvt','started');
myFactory.process().then(function() {
$scope.$emit('messageEvt','ended');
});
}]);
angular.module('app').controller('Cntrl2',
['$scope', '$q', '$timeout', $rootScope,
function ($scope, $q, $timeout, $rootScope) {
$rootScope.$on('messageEvt',function(e,msg) {
$scope.message = msg;
}
}]);
angular.module('app').factory('myFactory',
['$window', '$q','$timeout',
function($window, $q,$timeout) {
var x;
return {
process: function() {
var deferObj = $q.defer();
$timeout(function() {
deferObj.resolve(x);
});
return deferObj.promise;
},
};
}]);

I think better way to do this is by having factory maintain the model and both controllers updating it when needed.
I updated the fiddle to http://jsfiddle.net/hh5Cy/2/
angular.module('app').factory('Share_scope',
['$window', '$q',
function($window, $q) {
var x;
return {
getProcess: function() {
return x;
},
setProcess: function(value){
x = value;
}
};
}]);
Please let me know if I understood you wrongly.

Related

Unable to call function as $rootScope is undefined

I am trying to call the function inside the controller 'Notification' when getNotification is called in the SelectNotificationCtlr. However when running this I get an Error stating that $rootScope is undefined on the line below console.log("log");. I have tried passing the $rootScope as a parameter in my getNotification function but still receive the same error.
Please see my code below, any advice or help would be really appreciated.
app.js
selectNotification.controller('selectNotificationCtlr', ['$scope', '$rootScope', 'notificationsService',
function($scope, $http, notificationsService, notificationService, $rootScope) {
$scope.getNotification = function() {
var id = $scope.selectedNotification;
notificationData = notificationsService.getNotifications();
console.log(notificationData);
console.log("log");
$rootScope.$emit("call", {});
}
}
]);
selectNotification.controller('Notification', ['$scope', '$rootScope',
function($scope, $rootScope) {
$rootScope.$on("call", function() {
$scope.parent(notificationService);
});
$scope.parent = function() {
console.log("log");
}
}
]);
Kind regards
CB
Your controller should have dependencies in the right order,
selectNotification.controller('selectNotificationCtlr', ['$scope', '$rootScope', 'notificationsService',
function($scope, $rootScope, notificationsService) {

AngularJS - controller and factory - where am I going wrong at include/inject functions?

I'm new to Angular and cannot pinpoint where I am going wrong. I'm just trying to simply inject my factory into my controller, reference said: "Cannot read property 'validar' of undefined". I have two files, ServiceUtil.js where have a service and CentroCustoCtrl.js where I'm trying to use service's function.
The function at ServiceUtil.js:
(function () {
'use strict';
angular.module('Services', [])
.service('ValidarFormulario', [function () {
this.validar = function (form) {
var valido = true;
//code
}
return valido;
}
}]);
})();
And CentroCustoCtrl.js
(function () {
'use strict';
var app = angular.module("start", ['AxelSoft', 'ngLocalize',
'ngLocalize.Config', 'mvComponentes','Services'])
.value('localeConf', {
basePath: '../Scripts/Locales', ...
...
});
app.controller('CentroCustoCtrl', ['$scope', '$http', 'ValidarFormulario', function ($scope, $http, $rootScope, $timeout, ValidarFormulario) {
$scope.Salvar = function () {
if (ValidarFormulario.validar(document.getElementsByTagName('input'))) { ...// Cannot read property 'validar' of undefined
);
I tried with factory , but not worked too:
angular.module('Services', [])
.factory('ValidarFormulario', [function () {
return{
validar : function (form) {
var valido = true;
//code
}
}
return valido;
}
}
}]);
})();
Please, I appreciate any help you can provide.
The problem is you had wrong dependency sequence inside DI inline array, basically they are mismatching in number and their sequences
app.controller('CentroCustoCtrl', ['$scope', '$http', 'ValidarFormulario',
//removed $rootScope, $timeout which wasn't used.
function ($scope, $http, ValidarFormulario) {
OR either way you could just add the dependency inside array, if they are really gonna used inside controller like below
app.controller('CentroCustoCtrl', ['$scope','$http','$rootScope','$timeout','ValidarFormulario',
function ($scope, $http, $rootScope, $timeout, ValidarFormulario) {
Just change the below line of code
app.controller('CentroCustoCtrl', ['$scope', '$http', 'ValidarFormulario', function ($scope, $http, $rootScope, $timeout, ValidarFormulario) {
to
app.controller('CentroCustoCtrl', ['$scope', '$http', '$rootScope', '$timeout', 'ValidarFormulario', function ($scope, $http, $rootScope, $timeout, ValidarFormulario) {
This should work.
Well, also I've saw that your controller injections are wrong. You have:
App.controller('CentroCustoCtrl', ['$scope', '$http', 'ValidarFormulario', function ($scope, $http, $rootScope, $timeout, ValidarFormulario)
And you should have:
app.controller('CentroCustoCtrl', ['$scope', '$http', '$rootScope', '$timeout', 'ValidarFormulario', function ($scope, $http, $rootScope,$timeout, ValidarFormulario)
Injectors on "[ ]" must mach with function parameters.
When you set a module the syntax is:
angular.module('Services', [ here injections ])
But when you get a module to use it, syntax must be:
angular.module('Services')

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

angular service injection in controller with multiple methods

I'm trying to build a ionic object-oriented controller properly and am getting trouble with Service Injection...
angular.module('app.controllers', ['ionic', 'app.services.myservice']).controller('myCtrl', MyCtrl)
function MyCtrl($scope, $ionicLoading, MyService){
this.scope = $scope;
this.ionicLoading = $ionicLoading;
this.MyService = MyService;
}
MapCtrl.prototype.method1 = function($scope, $ionicLoading, MyService) {
//$scope, $ionicLoading and MyService are undefined
}
MapCtrl.prototype.method2 = function(){
this.scope.dummy = "A"; //That's ok!
this.MyService.aMethodWithCallBack(function(res){
//this.ionicLoading or this.MyService are undefined in this scope !
}
}
How would you handle it, properly?
I prefer next way
MyCtrl.$inject = ['$scope', '$ionicLoading', 'MyService'];
function MyCtrl($scope, $ionicLoading, MyService) {
// Act as ViewModel
var vm = this;
vm.method1 = function() {
MyService.getData().then(function(response) {
vm.data = response;
});
};
}
Your issue is that you did not inject the dependencies :
angular.module('app.controllers', ['ionic', 'app.services.myservice']).controller('myCtrl', ['$scope', '$ionicLoading', 'MyService', MyCtrl])
function MyCtrl($scope, $ionicLoading, MyService){
}
This should work
To make it more clear, I suggest you to declare controllers that way :
var controllers = angular.module('app.controllers', ['ionic', 'app.services.myservice']);
controllers.controller('myCtrl', ['$scope', '$ionicLoading', 'MyService', MyCtrl]);
function MyCtrl($scope, $ionicLoading, MyService){
}

Factory in angularJS

Im trying to use a factory in angularJS, but I don't work as expected.
Here is my controller:
as.controller('Test', ['testFactory', function($scope, $http, $rootScope)
{
$http.get($rootScope.appUrl + '/nao/test/test')
.success(function(data, status, headers, config) {
$scope.test = data;
});
$scope.form = {};
$scope.submitForm = function(isValid) {
if(isValid)
{
testFactory.testFactoryMethod(function($http) {
$scope.test = data;
});
}
};
}]);
As you can see, I "include" my factory to the controller.
Here is my factory:
.factory('testFactory', function($http) {
return {
testFactoryMethod: function(callback) {
return $http('http://127.0.0.1:81/test/test', data).success(function(data) { callback(data);
});
}
};
});
When I run this, I get this error message:
Error: $http is undefined
#http://127.0.0.1:82/nao/js/controllers.js:82:3
Anyone who can help me?
This happens because of Angular $injector. When you provide an array as 2nd argument for .controller, the $injector tries to find all dependencies listed on it by their name and then inject them to the array's last element (which must be a function), so in your case, this is what happens:
'testFactory' -> $scope
undefined -> $http
undefined -> $rootScope
Your code should be either like this:
as.controller('Test', ['$scope', '$http', '$rootScope', 'testFactory', function($scope, $http, $rootScope, testFactory)
{
// ...
... or like this:
as.controller('Test', function($scope, $http, $rootScope, testFactory)
{
// ...
Edit: As #sp00m stated, the second example should not be used if you are going to uglify (minify) your code, because the uglifier algorithm will replace those identifiers with something like:
function(a, b, c, d)
And then AngularJS will not be able to find those dependencies anymore, whereas the first example would look like this:
['$scope', '$http', '$rootScope', 'testFactory', function(a, b, c, d)
Which is valid, because you are explicitly telling Angular which dependencies it must inject.
There is a problem with the dependencies in your controller. The names you have as strings in the array don't match the arguments to your factory function.
This should work:
as.controller('Test', ['$scope', '$http', '$rootScope', 'testFactory', function($scope, $http, $rootScope, testFactory)
{
$http.get($rootScope.appUrl + '/nao/test/test')
.success(function(data, status, headers, config) {
$scope.test = data;
});
$scope.form = {};
$scope.submitForm = function(isValid) {
if(isValid)
{
testFactory.testFactoryMethod(function($http) {
$scope.test = data;
});
}
};
}]);
I think you're forgetting the $http.post:
$http(url, data) should be $http.post(url, data)
And what others have said before, you need the testFactory injected in the controllers function.
You should declare your controller like this
as.controller('Test', ['$scope', '$http', '$rootScope', 'testFactory', function($scope, $http, $rootScope, testFactory)
{
....
}

Categories

Resources