I come to you because I do not know how to access two different controllers to a global function.
I try to access a generic function that should be called two different controllers. The disconnect feature allows you to disconnect from the application, but also reset the global variables.
controller_1 and controller_2:
function CONTROLLER_1 ($scope, $rootScope) {
$scope.disconnect = function() {
// RESET $rootScope variable
$rootScope.var1 = 0;
$rootScope.var2 = 0;
etc...
};
}
function CONTROLLER_2 ($scope, $rootScope) {
$scope.disconnect = function() {
// RESET $rootScope variable
$rootScope.var1 = 0;
$rootScope.var2 = 0;
etc...
};
}
I would like something like this:
function CONTROLLER_1 ($scope, $rootScope) {
$scope.disconnect = function() {
//CALL GLOBAL_METHOD
}
}
function CONTROLLER_2 ($scope, $rootScope) {
$scope.disconnect = function() {
//CALL GLOBAL_METHOD
}
}
My GLOBAL_METHOD {
// RESET $rootScope variable
$rootScope.var1 = 0;
$rootScope.var2 = 0;
etc...
}
Is it possible to have a similar solution in this case?
If I'm not precise enough, do not hesitate to ask me for more information
Thank you for your help.
It seems that you should use a service for that:
I can see two solutions:
1°) Since each controllers inherit from rootScope, you can define disconnect function on rootScope you will be able to call disconnect automatically:
angular.module('app').run(['$rootScope', function($rootScope) {
$rootScope.disconnect = function() {
$rootScope.var1 = 0;
$rootScope.var2 = 0;
};
}]);
angular.controller('Ctrl1', ['$scope', '$rootScope', function($scope, $rootScope) {
// Disconnect function is already define
$scope.applyDisconnect = function() {
$scope.disconnect(); // Or $rootScope.disconnect();
};
}]);
angular.controller('Ctrl2', ['$scope', '$rootScope', function($scope, $rootScope) {
// Disconnect function is already define
}]);
Be careful, you should not redefine disconnect function.
See this fiddle: http://jsfiddle.net/37cMw/2
2°) Use a dedicated service and inject it in your controllers:
angular.module('myApp').service('DisconnectService', ['$rootScope' function($scope) {
this.disconnect = function() {
$rootScope.var1 = 0;
$rootScope.var2 = 0;
};
}]);
angular.module('myApp').controller('Ctrl1', ['$scope', 'DisconnectService', function($scope, service) {
$scope.disconnect = function() {
service.disconnect();
};
}]);
angular.module('myApp').controller('Ctrl2', ['$scope', 'DisconnectService', function($scope, service) {
$scope.disconnect = function() {
service.disconnect();
};
}]);
See this fiddle: http://jsfiddle.net/QFvyj/
Second solution is my favourite since you don't pollute rootScope namespace.
Yes you can! Add the method to the .run of your module
angular.module('app').run(function($rootScope) {
$rootScope.GLOBAL_METHOD = function() {
//YOUR STUFF
})
})
And you can call this method from every controller like this:
$rootScope.GLOBAL_METHOD();
So in your case:
function CONTROLLER_1 ($scope, $rootScope) {
$scope.disconnect = function() {
$rootScope.GLOBAL_METHOD();
}
}
function CONTROLLER_2 ($scope, $rootScope) {
$scope.disconnect = function() {
$rootScope.GLOBAL_METHOD();
}
}
While the provided solution by user2874153 would probably work, it's best to avoid polluting the $rootScope. To share functions between controllers you should create a service.
You should also avoid declaring controllers in the global namespace, and should use the angular.module syntax instead (see http://docs.angularjs.org/guide/controller#setting-up-the-initial-state-of-a-object, the part where it says 'NOTE: ').
angular.module('myApp', []);
angular.module('myApp')
.controller('OneCtrl', function ($scope, SharedService) {
SharedService.doSomething();
});
angular.module('myApp')
.controller('TwoCtrl', function ($scope, SharedService) {
SharedService.doSomething();
});
angular.module('myApp')
.service('SharedService', function () {
return {
doSomething: function () {
// do something here.
}
};
});
Related
I have a controller that updates my awards scope:
Controller 1
.controller("awardController", ['$scope', '$rootScope', 'Restangular', "$q", "$location", "TokenRestangular",
function ($scope, $rootScope, Restangular, $q, $location, TokenRestangular) {
$scope.updateAwardScope = function () {
resource = TokenRestangular.all('award');
resource.getList()
.then(function (awards) {
$scope.awards = awards;
})
}
}])
Controller 2
I have another controller 2 with a click event thats outside of this controllers scope. Is it possible for the controller below to call the $scope.updateAwardScope function from controller 1?
.controller('MainController', function ($rootScope, $scope) {
$scope.updateAwardScopeClick = function () {
// somehow call function from controller 1
}
});
I've found the use of the factory/service pattern to be a very effective way of reusing code in angular applications. For this particular case you could create an AwardFactory, inject it in your controllers and then call the update function. i.e
AwardFactory
myApp.factory('AwardFactory', ['TokenRestangular', function(TokenRestangular.all) {
var factory = {
awards: []
};
factory.update = function() {
resource = TokenRestangular.all('award');
resource.getList().then(function (awards) {
factory.awards = awards;
});
return factory.awards; // You can skip the return if you'd like that
};
return factory;
}]);
YourController
.controller('MainController', function ($rootScope, $scope, AwardFactory) {
$scope.updateAwardScopeClick = function () {
AwardFactory.update();
}
});
Hope it helps!
You can use angular broadcast and receive
Controller1
.controller("awardController", ['$scope', '$rootScope', 'Restangular', "$q", "$location", "TokenRestangular",
function ($scope, $rootScope, Restangular, $q, $location, TokenRestangular) {
$scope.updateAwardScope = function () {
resource = TokenRestangular.all('award');
resource.getList()
.then(function (awards) {
$scope.awards = awards;
$rootScope.broadcast("update.awards");
})
}
}])
Controller 2
.controller('MainController', function ($rootScope, $scope) {
$rootScope.$on('update.awards', function(){
$scope.updateAwardScopeClick();
});
$scope.updateAwardScopeClick = function () {
// somehow call function from controller 1
}
});
I have the following code factory:
angular.module('common')
.factory('_g',
['$http', '$q', '$resource', '$rootScope', '$timeout', '_o', '_u',
function ($http, $q, $resource, $rootScope, $timeout, _o, _u) {
var _init = function ($scope) {
$scope.modalReset = function () {
_modalReset($scope); // << No modalForm appears on this scope
};
};
var _modalReset = function ($scope) {
$scope.modalForm.$setPristine();
};
return {
init: _init,
modalReset: _modalReset
}
In my controller I initialize the service like this at the start of the code:
_g.init($scope);
On my page I have a form:
<form class="form" name="modalForm">
<button data-ng-click="modalReset()">
Reset
</button>
From what I learned this form will be added to the scope dynamically and appear as $scope.modalForm
When my form calls $scope.modalReset it executes BUT there is no modalForm on the $scope when I check it with the debugger.
Can someone explain why this is. What it seems like is that the service is being passed the
scope at an early stage before the modalForm has been added. Is this the case and is there a
way that I can solve this problem?
First of all its not good practice to use $scope into factory/service. Services are Singletons.
This logic you can write in directive or controller.
Anyways, from your example I don't see you pass somehow $scope as argument to both methods. I would change factory to:
angular.module('common')
.factory('_g',
['$http', '$q', '$resource', '$rootScope', '$timeout', '_o', '_u',
function ($http, $q, $resource, $rootScope, $timeout, _o, _u) {
var _init = function ($scope) {
$scope.modalReset = function () {
_modalReset($scope); // << No modalForm appears on this scope
};
};
var _modalReset = function ($scope) {
$scope.modalForm.$setPristine();
};
return {
init: function ($scope) {
return _init($scope) ;
},
_modalReset: function ($scope) {
return _init($scope) ;
}
}
}]);
I have a partial view that is using angular. How do I change a variable in the MainController from PartialController? I am not sure how to create the interdependence...
angularApp.controller('MainController', ['$scope', '$http', '$compile', function MainController($scope, $http, $compile) {
$scope.myVariable = "0";
//Had the following before refactoring due to repetitive code.
//Code now in PartialController
//$scope.searchData = function ($event) {
// //code
// $scope.myVariable = "1";
//}
}]);
angularApp.controller('PartialController', ['$scope', '$http', '$compile', function PartialController($scope, $http, $compile) {
$scope.searchData = function ($event) {
//code
$scope.myVariable = "1";
}
}]);
For sake of completeness, there are at least 3 ways:
With a service as #tymeJV suggested (BEST answer)
app.factory('dataStore', function () {
var dataStore = {};
return dataStore;
});
app.controller('ParentCtrl', function($scope, dataStore) {
$scope.dataStore = dataStore;
$scope.dataStore.foo = 'bar';
});
app.controller('ChildCtrl', function($scope, dataStore) {
dataStore.foo = 'not bar anymore';
});
With an object reference on the parent scope (A bit hackish)
app.controller('ParentCtrl', function($scope) {
$scope.data = {
foo: 'bar'
};
});
app.controller('ChildCtrl', function($scope) {
$scope.data.foo = 'not bar anymore';
});
With $parent (equally hackish)
app.controller('ParentCtrl', function($scope) {
$scope.foo = 'bar';
});
app.controller('ChildCtrl', function($scope) {
$scope.$parent.foo = 'not bar anymore';
});
Why are #2 and #3 hackish?
Because they create a dependency in your ChildCtrl of having it always be a child of the ParentCtrl... otherwise it will break.
So why include #2 and #3 at all?
For a few reasons:
Directives can have controllers, and required parent directives. Because of this, there are cases where you can "safely" use $parent or scope inheritance because you'll always know that ChildCtrl has ParentCtrl as a parent.
Sometimes you just need to hack something together.
As I said, for the sake of completeness.
This is a prime use for a service that can be injected to controllers when you need it and pull data from it:
app.factory("myService", function() {
var myVariable = null;
return {
get: function() {
return myVariable;
},
set: function(value) {
myVariable = value;
}
}
});
//Inject
angularApp.controller('MainController', ['$scope', '$http', 'myService', '$compile', function MainController($scope, $http, $compile, myService) {
myService.set(3);
});
tymeJV's answer is correct and is probably best practice in this case. I believe the reason it wasn't working in your example is because in Javascript, primitives (strings, numbers, booleans) are passed by value, whereas objects are passed by reference.
i.e. if you had $scope.obj.myVariable=1 in your main controller and edit $scope.obj.myVariable in your child controller, you should see the new value in both. (this is kinda #2 in blesh's answer). This is a common source of "bugs" in Angular so it's good to be aware of it.
I have a Service and a Controller. The controller calls a function, getItems() on the Service. The Service returns an array of data.
However, the controller appears to not be receiving this, oddly enough.
Controller:
ItemModule.controller('ItemController', ['$scope', 'ItemService',
function ($scope, ItemService) {
$scope.items = [];
$scope.getItems = function() {
$scope.items = ItemService.getItems();
}
$scope.getItems();
}
]);
Service:
ItemModule.service('ItemService', ['$rootScope', '$http',
function($rootScope, $http) {
this.getItems = function() {
$http.get($rootScope.root + '/products').success(function(data) {
// This prints it out fine to the console
console.log(data);
return data;
});
}
}
]);
What am I doing wrong?
A quick and dirty fix would be like that:
ItemModule.service('ItemService', ['$rootScope', '$http',
function($rootScope, $http) {
return {
getItems : function(scope) {
$http.get($rootScope.root + '/products').success(function(data) {
scope.items = data;
});
}
}
}
]);
and then in your controller just call:
ItemService.getItems($scope);
But if your controller is a part of route (and probably is) it would be much nicer to use resolve (look here).
I am trying to call a scope function inside the controller. My aim is to call the function in the load itself.
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$scope.functionname();
$scope.functionname = function() {}
});
You can directly call the function in controller.
app.controller('customersCtrl', function($scope, $http) {
functionname();
function functionname {
//do something.
}
});
If you are looking to reuse the function outside controller then use Service as controllers are not injectable.
Read johnpapa style guide which shows best practices: https://github.com/johnpapa/angular-styleguide
app.controller('customersCtrl', function(someService) {
var vm = this;
activate();
function activate() {
// Do something.. You can get the data from your service
}
});
Then do your $http in services then inject it in your controller/s.
Best way is to use services:
var app = angular.module('myApp', []);
app.service('SomeService', ['$state', function ($state) {
this.someFunction = function() {
return "some value";
};
}]);
app.controller('customersCtrl', function($scope, $http, SomeService) {
SomeService.someFunction();
});