Angular $on not working - angularjs

I have two controllers (Main controller and Child controller). I am trying to pass value from Main to Child controller.
Here are the controllers:
.controller('mainController', ['$scope', '$rootScope', '$location', 'CIFactory', function ($scope, $rootScope, $location, CIFactory) {
$scope.moveTool = function (buildServerTool) { //Am calling this moveTool function from View
$scope.tool = buildServerTool.toolname;
$scope.$broadcast('update_parent_controller', $scope.tool);
};
}])
.controller('childController', ['$scope', '$rootScope', '$q', '$timeout', '$log', 'CIFactory', function ($scope, $rootScope, $q, $timeout, $log, CIFactory) {
$scope.$on('update_parent_controller', function (event, tools) {
$scope.tools = tools;
});
}])
When I debug, control is going in moveTool() function, but it is not going inside $on(i.e., value in tools is not assigned to $scope.tools. What am I doing wrong here ?

As Martijn said $broadcast moves down the $scope chain, so it may be best to use $rootScope if the child controller isnt directly inside the parent scope
$rootScope.$broadcast('update_parent_controller', $scope.tool);
See this answer for more information on emit vs broadcast and scopes

Thanks Chris. I have also tried another method and it worked for me. Instead of using $broadcast and $on, I just used following line in child controller,
$scope.tools = $scope.$parent.tool;
So, the above code took the $scope value from parent controller and assigned to new scope $scope.tools, which I have used in corresponding View.

Related

How to send events with AngularJs $emit properly

I want to send data from one controller to another at a certain point. I have looked at the docs and googled before for solutions before posting. But can`t seem to get it to work properly.
I know $emit is for sending events up the scope hierarchy and $braodcast is for telegraphing downwards.
var app = angular.module('App.Controllers', ['ui.bootstrap'])
.controller('FordelaPaBetankandeCtrl',
['$rootScope', '$scope',
function ($rootScope, $scope) {
$scope.$on("delatYrkande", function (selectedValue) {
});
}])
.controller('UtskottCtrl',
['$rootScope', '$scope'
function ($rootScope, $scope) {
}])
.controller('TidlinjeCtrl',
['$rootScope', '$scope'
function ($rootScope, $scope) {
}])
.controller('UserInfoCtrl', ['$scope',
function ($scope){
}])
.controller('VisaSammantradesplanCtrl', ['$rootScope', '$scope',
function ($rootscope, $scope) {
}])
.controller('HanteraGrunddokumentCtrl',
['$rootScope', '$scope',
function ($rootScope, $scope) {
$scope.Emit = function (selectedValue) {
$scope.$emit("delatYrkande", selectedValue);
}
}]);
One approach is to broadcast from $rootScope:
$scope.Emit = function (selectedValue) {
̶$̶s̶c̶o̶p̶e̶.̶$̶e̶m̶i̶t̶(̶"̶d̶e̶l̶a̶t̶Y̶r̶k̶a̶n̶d̶e̶"̶,̶ ̶s̶e̶l̶e̶c̶t̶e̶d̶V̶a̶l̶u̶e̶)̶;̶
$scope.$root.$broadcast("delatYrkande", selectedValue);
}
For more information, see
AngularJS Developer Guide - Scope Events Propagation
AngularJS scope API Reference - $root
AngularJS scope API Reference - $broadcast

Service function not found in angular app

I added a service to my angular controller, but it says every time there is no function. I really dont know why and hope there is someone who can help me.
Here is my userCtrl.js http://hastebin.com/imufehimaw.js
You haven't injected the service in controller
Change
controller('userCtrl', function($scope, $http) {
To
controller('userCtrl', function($scope, $http, ergastAPIservice) {
You should inject your service as a dependency to your controller as shown below before using it
controller('userCtrl', function($scope, $http, ergastAPIservice) {
//your code
});
better way of using it if you are considering minimizing in future
controller('userCtrl', ['$scope', '$http', 'ergastAPIservice', function($scope, $http, ergastAPIservice) {
//your code
}]);

AngularJS: How to pass arguments to controller when it is registered?

Say I have a controller:
app.controller('HomeCtrl', Com.Xyz.ModuleHome.HomeController);
Com.Xyz.ModuleHome.HomeController is a controller function which has parameters like $scope, $window, $timeout, $http, ... these parameters are injected by AngularJS.
But I want to pass some parameters to the controller when it is registered. This is because my controllers are loaded from different domains by RequireJS, now I want to a controller to know where itself is from.
var myVar = jsFileUrl; // jsFileUrl is provided by RequireJS
// I wish the code looks like below
app.controller('HomeCtrl', Com.Xyz.ModuleHome.HomeController, myVar);
// AngularJS will inject a $controllerContext representing controller itself
function Com.Xyz.ModuleHome.HomeController($controllerContext, $scope) {
$scope.controllerJsFileUrl = $controllerContext.Argument;
}
Is it possible? Maybe there is something I didn't know.
I know a service can do it, but I don't want the controller to depend on a special service name. In the future I may move the controllers to somewhereelse.
Since you are looking for the anti-pattern, you could try using function.bindand pass the argument in the bound function. This will let the value of myVar to be passed in as first argument when the constructor is invoked (everytime).
app.controller('HomeCtrl', Com.Xyz.ModuleHome.HomeController.bind(null, myVar));
var app = angular.module('app', []);
var myVar = 1234;
function Ctrl(myVar, $q, $http) {
console.log(arguments);
}
app.controller('ctrl', ['$q', '$http', Ctrl.bind(null, myVar)]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
</div>
The above approach though short is tricky because you can no longer use controller instance as this as it would not the controller instance anymore instead it would be window. Another way is to create a dummy wrapper for the controller and new up the actual constructor.
.controller('ctrl', ['$q', '$http', function($q, $http) {
return new Ctrl(myVar, $q, $http);
}
]);

Can't inject $q in Angular?

everyone.
I have a really strange (for me) problem here. I am trying to inject the $q lib in one of my controllers and when I try to console.log() it, it returns "undefined". I am injecting the same library in one of my services, and it's working there! Let me show you:
The service:
(function() { 'use strict';
angular
.module('app.grid')
.factory('GridData', GridData);
GridData.$inject = ['$http', '$q'];
function GridData($http, $q) {
...
The controller (not working):
(function() {
'use strict';
angular
.module('app.grid')
.controller('GridCtrl', GridCtrl);
GridCtrl.$inject = ['$log', '$scope', 'GridData', '$q'];
function GridCtrl($log, $scope, GridData, $rootScope, $q) {
console.log($q); // Returns "undefined"
...
I wonder if any of you guys had had this same problem before? It's probably something real stupid, like it always is, but I can't see it for some reason :(
Cheers,
H
You need to add the $rootScope to your $inject array:
GridCtrl.$inject = ['$log', '$scope', 'GridData', '$rootScope', '$q'];
Or remove it from the argument list if it's not needed:
function GridCtrl($log, $scope, GridData, $q) {
You have one too many arguments:
GridCtrl.$inject = ['$log', '$scope', 'GridData', '$q'];
function GridCtrl($log, $scope, GridData, $rootScope, $q) {
// ^
}
You're not injecting $rootScope. The $q service will be available inside your controller, it will just be referred to by $rootScope instead of $q. Remove that and it should work! Alternatively, add '$rootScope to the dependency array.

Injecting $http and $scope into function within controller

I asked a similar question earlier when attempting to inject $scope and $http into a controller Cannot call method 'jsonp' of undefined in Angular.js controller. Now I'm attempting to refactor that code slightly by moving the code into a function within the controller. I'm encountering similar issues and can't seem to grasp the mechanics of dependency injection in Angular. Below is my new code. Both $scope and $http are undefined. What I'm attempting to do is make an http request when didSelectLanguage() fires and assign the resulting data to the "image" variable in the $scope from the parent controller. Can someone enlighten me as to how dependency injection is supposed to work in this example?
angular.module('myApp.controllers', []).
controller('ImagesCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.didSelectLanguage=function($scope, $http) {
console.log($scope);
$http.jsonp('http://localhost:3000/image?quantity=1&language='+this.language+'&Flag=&callback=JSON_CALLBACK')
.success(function(data){
$scope.image = data;
});
}
}])
When you create your controller:
angular.module('myApp.controllers', []).
controller('ImagesCtrl', ['$scope', '$http', function ($scope, $http) {
// ...
}]);
The stuff inside the body of the controller function automatically has access to $scope and $http because of closures. Thus, there's no need to specify anything additional for a function on the $scope to have access to these things:
angular.module('myApp.controllers', []).
controller('ImagesCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.didSelectLanguage = function() {
$http.jsonp('http://localhost:3000/image?quantity=1&language=' + this.language + '&Flag=&callback=JSON_CALLBACK');
.success(function(data) {
$scope.$parent.image = data;
});
}
}]);
When didSelectLanguage is run, it sees the references to $http, and reaches out of the function into the outer function to get the value of the reference; the same happens for $scope inside the success callback.
So, in short, there's no need to pass any arguments to your didSelectLanguage function, nor is there in this case any reason to use the $injector.
With the help of Michelle Tilley's comment & article I solved the problem as follows. However, I'm going to keep the question open until someone else answers or until I understand enough to write an accompanying explanation.
controller('ImagesCtrl', ['$scope', '$http', '$injector', function ($scope, $http, $injector) {
$scope.didSelectLanguage=function() {
$http.jsonp('http://localhost:3000/image?quantity=1&language='+this.language+'&Flag=&callback=JSON_CALLBACK')
.success(function(data){
$scope.$parent.image = data;
});
}
}])

Resources