AngularJS $injector.invoke - ParentController is not defined - angularjs

I have 2 controllers defined:
var myApp = angular.module('nestedControllersModule',[]);
myApp.controller('ParentController', ['$scope', function($scope) {
}]);
myApp.controller('ChildController', ['$scope', '$injector', function($scope, $injector) {
$injector.invoke(ParentController, this, {$scope: $scope});
}]);
This gives: ReferenceError: ParentController is not defined.
This code works only if ParentController is defined as:
function ParentController($scope) {}
I am trying to inject the parent in the child as then I can inherit the common functions defined in the parent.
var myApp = angular.module('nestedControllersModule',[]);
myApp.controller('ParentController', ['$scope', function($scope) {
$scope.name = 'ParentName';
$scope.Type = 'ParentType';
$scope.clickme = function() {
alert('This is parent controller "ParentController" calling');
}
}]);
myApp.controller('ChildController', ['$scope', '$injector', '$ParentController', function($scope, $injector, $ParentController) {
$injector.invoke(ParentController, this, {$scope: $scope});
$scope.name = 'Child';
}]);

myApp.controller('ParentController', ['$scope', function($scope) {
}]);
myApp.controller('ChildController', ['$scope', 'ParentController', function($scope, ParentController) {
// ok now you have ParentController
}]);
But I think you need to use Services to share data/functions between Controllers or using PubSub model:
What's the correct way to communicate between controllers in AngularJS?
This reduces coupling between parts of your app.

This is a basic workaround to achieve what you're after:
var myApp = angular.module('nestedControllersModule',[]);
myApp.factory('ParentControllerFactory', function () {
function ParentControllerFactory($scope) {
$scope.name = 'ParentName';
$scope.Type = 'ParentType';
$scope.clickme = function() {
alert('This is parent controller "ParentController" calling');
}
}
return (ParentControllerFactory);
})
.controller('ParentController', ['$scope', '$injector', 'ParentControllerFactory', function ($scope, $injector, ParentControllerFactory) {
$injector.invoke(ParentControllerFactory, this, {
$scope: $scope
});
}])
.controller('ChildController', ['$scope', '$injector', 'ParentControllerFactory', function ($scope, $injector, ParentControllerFactory) {
$injector.invoke(ParentControllerFactory, this, {
$scope: $scope
});
}]);
I say workaround because it's probably worthwhile looking into properly implementing a service to manage any commonality as previously mentioned (or better yet, splitting commonality into directives, clickme for example is a good candidate)
...also note that $injector.invoke(ParentControllerFactory as it is above will most likely chuck a hissy fit if/when you minify your scripts later on, so be careful where and how it used.

Consider using the Mixin pattern possible by using the $controller service.
In your example, you would replace the $injector service with the $controller service:
var myApp = angular.module('nestedControllersModule',[]);
myApp.controller('ParentController', ['$scope', function($scope) {
$scope.name = 'ParentName';
$scope.Type = 'ParentType';
$scope.clickme = function() {
alert('This is parent controller "ParentController" calling');
}
}]);
myApp.controller('ChildController', ['$scope', '$controller', '$ParentController', function($scope, $controller, $ParentController) {
$controller('ParentController',{$scope: $scope})
$scope.name = 'Child';
}]);
This is a good overview of using the $controller service:
http://vadimpopa.com/split-large-angularjs-controllers-using-the-mixin-pattern/

Related

how to passing data from one controller to another controller using angular js 1

hi all i using angular js i need to transfer the value from one page controller to another page controller and get that value into an a scope anybody help how to do this
code Page1.html
var app = angular.module("app", ["xeditable", "angularUtils.directives.dirPagination", "ngNotify", "ngCookies","ngRoute"]);
app.controller('Controller1', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore',
function ($scope, $http, $window, $filter, $notify, $cookieStore)
{
$scope.Message="Hi welcome"
}]);
now i want to show scope message into page2 controller
var app = angular.module("app", ["xeditable", "angularUtils.directives.dirPagination", "ngNotify", "ngCookies","ngRoute"]);
app.controller('Controller2', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore',
function ($scope, $http, $window, $filter, $notify, $cookieStore)
{
///here i want get that scope value
}]);
You can use $rootScope instead of $scope:
// do not forget to inject $rootScope as dependency
$rootScope.Message="Hi welcome";
But the best practice is using a service and share data and use it in any controller you want.
You should define a service and write getter/setter functions on this.
angular.module('app').service('msgService', function () {
var message;
this.setMsg = function (msg) {
message = msg;
};
this.getMsg = function () {
return message;
};
});
Now you should use the setMeg function in Controller1 and getMsg function in Controller2 after injecting the dependency like this.
app.controller('Controller1', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore', 'msgService',
function ($scope, $http, $window, $filter, $notify, $cookieStore, msgService)
{
$scope.Message="Hi welcome"
msgService.setMsg($scope.Message);
}]);
app.controller('Controller2', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore', 'msgService',
function ($scope, $http, $window, $filter, $notify, $cookieStore, msgService)
{
///here i want get that scope value
console.log('message from contoller 1 is : ', msgService.getMsg());
}]);
You should use services for it .
Services
app.factory('myService', function() {
var message= [];
return {
set: set,
get: get
}
function set(mes) {
message.push(mes)
}
function get() {
return message;
}
});
And in ctrl
ctrl1
$scope.message1= 'Hi';
myService.set($scope.message1);
ctrl2
var message = myService.get()
Sharing data from one controller to another using service
We can create a service to set and get the data between the controllers and then inject that service in the controller function where we want to use it.
Service :
app.service('setGetData', function() {
var data = '';
getData: function() { return data; },
setData: function(requestData) { data = requestData; }
});
Controllers :
app.controller('Controller1', ['setGetData',function(setGetData) {
// To set the data from the one controller
$scope.Message="Hi welcome";
setGetData.setData($scope.Message);
}]);
app.controller('Controller2', ['setGetData',function(setGetData) {
// To get the data from the another controller
var res = setGetData.getData();
console.log(res); // Hi welcome
}]);
Here, we can see that Controller1 is used for setting the data and Controller2 is used for getting the data. So, we can share the data from one controller to another controller like this.

How can I run function from another controller so scope is updated in angular?

In the example below, how can I run getData from another controller and have the scope variable in the view updated?
var app = angular.module('app', []);
app.factory('MyService', ['$http',function($http) {
return {
getData: function() {
return $http.get('/api/endpoint');
}
};
}]);
app.controller('MyController', ['$scope', '$http', 'MyService', function($scope, $http, MyService){
MyService.getData().then(function(response){
$scope.myVarialbe = response.data;
});
}]);
app.controller('MyController2', ['$scope', '$http', 'MyService', function($scope, $http, MyService){
///// ?????? How to get $scope.myVarialbe updated from the getData call?
});
}]);
Using $broadcast and $on :
$broadcast dispatches an event name downwards to all child scopes (and their children) and notify to the registered $Scope listeners. The event life cycle starts at the scope on which $broadcast was called. All listeners for the event on this scope get notified.
$on listen on events of a given type. It can catch the event dispatched by $broadcast
app.controller('MyController', ['$scope', '$http', 'MyService', function($scope, $http, MyService){
$scope.$on('variableChanged',function(event, value) {
$scope.myVariable = value;
};
}]);
app.controller('MyController2', ['$scope', '$http', 'MyService', function($scope, $http, MyService){
MyService.getData().then(function(response){
$scope.$broadcast('variableChanged', response.data);
});
}]);
angular.module('app').controller('nav', function($scope,$http) {
$rootScope.$on("CallMethodNavController", function(){
$scope.navMethod();
});
$scope.navMethod=function(){
$http.get('/players').then(function(data) {
$scope.numOfPlayers = data.players.length;
}
});
});
then in the second controller you call this method once a player is added like so:
$rootScope.$emit("CallMethodNavController", {});

angular $controller locals substitue

I am using $controller service to inherit controller.
I have something like this
angular.module('myModule', ['someModule'])
.controller('parentController', parentController)
.controller('childController', childController);
parentController.$inject = [ '$scope', 'someModule.defaultService'];
childController.$inject = [ '$scope', 'someModule.myService'];
function parentController($scope, defaultService) {
$scope.value = defaultService.someMethod();
}
function childController($scope, myService) {
var viewModel = this;
var ctrl = $controller('parentController', {
$scope: $scope, defaultService:myService
});
angular.extend(viewModel, ctrl);
}
I want to parentController using myService insted of it's defaultService. But it doesn't work. How can i solve this problem?
uses the correct injection name :
var ctrl = $controller('parentController', {
$scope: $scope, **defaultService**:myService
});
But what you're doing seems more of an hack than anything else imho.

Can I have two angular.module calls to the same ng-app in two different files for same controller?

Hi I have created two angulerjs files for same ng-app example.
admin.js
var app = angular.module('arcadminmodule', ['ngTable', 'ui-notification']);
app.controller('ArcAdminController', ['$http', '$scope', '$filter', '$interval', 'ngTableParams', 'Notification', function($http, $scope, $filter, $interval, ngTableParams, Notification) {});
admin1.js
var app = angular.module('arcadminmodule');
app.controller('ArcAdminController', ['$http', '$scope', '$filter', '$interval', 'ngTableParams', 'Notification', function($http, $scope, $filter, $interval, ngTableParams, Notification) {});
But its overriding admin.js from admin1.js
please help me out....
In admin1.js when you write:
var app = angular.module('arcadminmodule');
you are not creating a new module. You are trying to get an existing module named 'arcadminmodule'.. If you want to create a new module, you will have to write something like this:
var app = angular.module('arcadminmodule',[]); // add your depencencies...
Now, In your case, in admin.js you are creating your module and admin1,js you are making use of the same module. In angular you cannot have two controllers with the same name. Controllers are for (from the docs):
Set up the initial state of the $scope object.
Add behavior to the $scope object.
So If you need are trying to apply some roles or some business logic, It need to go into one controller. Make sure your controller contain only the business logic needed for a single view.
I think its no need for use the same controller in two places.But you can use services in places.If you need to do some think different from the ArcAdminController,use this structure.
Services
-service1.js
(function (angular) {
angular.module('marineControllers').service('boatService', function (ajaxService) {
}
)
-service2.js
-module..js
var artistControllers = angular.module('marineControllers',['ngAnimate']);
Controllers
-controller1
(function (angular) {
angular.module('marineControllers').controller("BoatController", ['$scope', '$http', '$routeParams',
'dashboardService', '$filter', 'loginService', '$location', 'boatService', 'autocompleteFactory', 'utilityFactory',
function ($scope, $http, $routeParams, dashboardService, $filter, loginService, $location, boatService, autocompleteFactory, utilityFactory) {
function loadAllFishingBoat() {
$scope.boatsTable.length = 0;
if (!$scope.$$phase)
$scope.$apply();
boatService.getAllBoatAndDevice().then(function (data) {
$scope.boatsTable = data;
if (!$scope.$$phase)
$scope.$apply();
});
};
}]);
})(angular);
-controller2
(function (angular) {
angular.module('marineControllers').controller("DeviceController", ['$scope', '$http', '$routeParams',
'dashboardService', '$filter', 'loginService', '$location', 'deviceService', 'autocompleteFactory', 'utilityFactory','commonDataService',
function ($scope, $http, $routeParams, dashboardService, $filter, loginService, $location, deviceService, autocompleteFactory, utilityFactory,commonDataService) {
function loadAllFishingBoat() {
$scope.boatsTable.length = 0;
if (!$scope.$$phase)
$scope.$apply();
boatService.getAllBoatAndDevice().then(function (data) {
$scope.boatsTable = data;
if (!$scope.$$phase)
$scope.$apply();
});
};
}]);
})(angular);
I have been use many services in both controllers,still they are different logics.

How can I call a scope function inside a controller?

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();
});

Resources