I am trying to share informations between two controllers with $scope.$on and $scope.$broadcast.
Here is the view:
<div ng-controller="ParentCtrl">
<div ng-controller="ChildCtrl">
{{content}}
</div>
</div>
and the controllers:
.controller('ParentCtrl', ['$scope', function($scope) {
$scope.$broadcast('someEvent', 'bidule');
}])
.controller('ChildCtrl', ['$scope', function($scope) {
$scope.$on('someEvent', function(event, b) {
$scope.content = b;
});
}])
and the plunker
What am I doing wrong here?
The child controller isn't instantiated yet. Wrapping the broadcast in a timeout works:
http://plnkr.co/edit/MF7P16K1OTv46JNgkkih?p=preview
$timeout(function(){
$scope.$broadcast('someEvent', 'bidule');
});
Child not initiated. Faced the same issue and this was my solution.
.controller('ParentCtrl', ['$scope', function($scope) {
$scope.$on('initiateEvent', function(event, b) {
$scope.$broadcast('someEvent', 'bidule');
}
}])
.controller('ChildCtrl', ['$scope', function($scope) {
$scope.$on('someEvent', function(event, b) {
$scope.content = b;
});
$scope.$emit('initiateEvent', null);
}])
Here i'm initiating the child and asking the parent to broadcast someEvent
To broadcast an event, you simply have to call it.
The following code works perfectly :
Your view :
<div ng-controller="ParentCtrl" ng-click="myFunc()">
<div ng-controller="ChildCtrl">
{{content}}
</div>
</div>
and your controllers :
.controller('ParentCtrl', ['$scope', function($scope) {
$scope.myFunc = function() {
$scope.$broadcast('someEvent', 'bidule');
}
}])
.controller('ChildCtrl', ['$scope', function($scope) {
$scope.$on('someEvent', function(event, b) {
$scope.content = b;
});
}])
Hope it helps !
Related
I'm trying to pass some data from child controller to parent controller using $emit + $on .
Here is my code.
angular.module('myApp', [])
.controller('parentCtrl', ['$scope', '$http', '$q', function ($scope, $http, $q) {
$scope.message = 'parent';
$scope.$on('EventFromChild', function (event, data) {
console.log("Event Received");
$scope.message = data;
});
}])
.controller('childCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.data ={"name":"Amit","lastname":"kumar"};
$scope.$emit('EventFromChild',$scope.data.name);
$scope.update = function(){
console.log("Clicked");
$scope.data.name ="Testing";
};
}]);
When page is loaded then, Then it successfully passes the data from the child to parent, But when I update the data in child then I also want it to get reflected in parent controller, But it is not emitting the event.
Plunker
It is because you are doing nothing when the child is updated.
You have to use $watch for observing changes. For example, if you want emit changes when data.name changes:
$scope.$watch('data.name', function() {
$scope.$emit('EventFromChild',$scope.data.name);
});
Or when any property of data changes:
$scope.$watch('data', function() {
$scope.$emit('EventFromChild',$scope.data);
});
This way the come becomes:
angular.module('app.controllers', [])
.controller('parentCtrl', ['$scope', '$http', '$q', function ($scope, $http, $q) {
$scope.message = 'parent';
$scope.$on('EventFromChild', function (event, data) {
console.log("Event Received");
$scope.message = data;
});
}])
.controller('childCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.data ={"name":"Amit","lastname":"kumar"};
$scope.$emit('EventFromChild',$scope.data.name);
$scope.update = function(){
console.log("Clicked");
$scope.data.name ="Testing";
};
$scope.$watch('data.name', function() {
$scope.$emit('EventFromChild', $scope.data.name);
});
}]);
Snippet:
// Code goes here
mc = angular.module('app', [
'app.controllers',
]);
angular.module('app.controllers', [])
.controller('parentCtrl', ['$scope', '$http', '$q', function ($scope, $http, $q) {
$scope.message = 'parent';
$scope.$on('EventFromChild', function (event, data) {
console.log("Event Received");
$scope.message = data;
});
}])
.controller('childCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.data ={"name":"Amit","lastname":"kumar"};
$scope.update = function(){
console.log("Clicked");
$scope.data.name ="Testing";
};
$scope.$watch('data.name', function() {
$scope.$emit('EventFromChild',$scope.data.name);
});
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.min.js"></script>
<div ng-app="app" ng-controller="parentCtrl">
<b>Parent Event:</b> {{message}}<br />
<br/><br/>
<div ng-controller="childCtrl">
<b>Child Event:</b> {{data.name}}<br />
<input type="button" ng-click="update()" value ="update"/>
</div>
</div>
I have an main page with ng-view defined.
My routing pulls in several templates.
config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
})
.when('/view2', {
templateUrl: 'view2/view2.html',
})
.otherwise({redirectTo: '/view1'});
}]);
My First template looks like this:
<p>This is the partial for view 1.</p>
<div ng-controller="View1Ctrl">
<input type="text"
ng-model="search"
ng-model-options="{ debounce: 800 }"
placeholder="Enter full movie name"
autofocus />
</div>
The JS for this template looks like this;
'use strict';
angular.module('myApp.view1', [])
.controller('View1Ctrl', [function($scope, $http) {
$scope.$watch('search', function() {
fetch();
});
function fetch(){
alert("it werky");
}
}]);
Why am I getting the error: angular.js:13708 TypeError: Cannot read property '$watch' of undefined?
I'm essentially pulling in a template with models and directives defined on it but I don't think those are being run.
May be your dependencies are not getting injected, you are passing an array with the constructor function as it's only element.
Here is a working plunk.http://plnkr.co/edit/U2hxQPBZMVo2jaR4bwsq?p=preview
myApp.controller('View1Ctrl', ['$scope', '$http', function($scope, $http) {
alert ("jaiHo");
$scope.$watch('search', function() {
fetch();
});
function fetch(){
alert("it werky");
}
}]);
Try this:
'use strict';
angular.module('myApp.view1', [])
.controller('View1Ctrl', ['$scope', '$http', function($scope, $http) {
$scope.$watch('search', function() {
fetch();
});
function fetch(){
alert("it werky");
}
}]);
Note how I inject dependencies
Try this
(function () {
'use strict';
angular.module('myApp.view1', [])
.controller('View1Ctrl', function($scope, $http) {
var vm = this;
$scope.$watch('vm.search', function(newValue, oldValue) {
fetch(newValue, oldValue);
}, true);
function fetch(newValue, oldValue){
vm.newValue = newValue;
vm.oldValue = oldValue;
}
});
}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp.view1">
<div ng-controller="View1Ctrl as vm">
<input ng-model="vm.search" type="text" />
<div>
Old Value: {{vm.oldValue}}
</div>
<div>
New Value: {{vm.newValue}}
</div>
</div>
</div>
I'm trying to get rootScope value in function from routeChangeSuccess in AngularJs as per following code. But I cannot convince why rootScope value is NULL when I output with console.log.
$rootScope.updateCurrentUser = function () {
$rootScope.loggedUser = "1";
};
$rootScope.$on('$routeChangeSuccess', function () {
var path = $location.path();
$rootScope.showIndex =
path === LANG_PATH + '/';
if ($rootScope.showIndex) {
//undefined result found :(
console.log('rootScope ' + $rootScope.loggedUser);
}
});
$rootScope.updateCurrentUser();
It's hard to tell since your example doesn't show where the handler is attached and where the change to $rootScope.loggedUser is made, but if it's happening in a controller, you probably won't the event.
Controllers don't get created until after the event has been broadcast, and the controller of the current view will be destroyed before the next $routeChangeSuccess event is broadcast, which means you'll miss the event if you're deregistering handlers in your controller's $destroy event.
In the snippet below, you'll see the event being handled (and $rootScope.eventLog updating) in .run as you change routes, but not in the handlers in the controllers.
angular.module('app', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/main', {
templateUrl: 'main.html',
controller: 'MainCtrl'
})
.when('/other', {
templateUrl: 'other.html',
controller: 'OtherCtrl'
})
.otherwise('/main');
}])
.run(['$rootScope', function($rootScope) {
$rootScope.eventLog = [];
$rootScope.$on('$routeChangeSuccess', function(e, curr, prev) {
// we should see this, and $rootScope.eventLog will get updated
$rootScope.eventLog.push({
handler: "Run",
event: e,
curr: curr,
prev: prev
});
});
}])
.controller('MainCtrl', ['$scope', '$rootScope',
function($scope, $rootScope) {
var deregister = $rootScope.$on('$routeChangeSuccess', function() {
// this won't happen: we'll deregister before the event is called
$rootScope.eventLog.push({
handler: "Main",
event: e,
curr: curr,
prev: prev
});
});
$scope.$on('$destroy', function() {
deregister();
});
}])
.controller('OtherCtrl', ['$scope', '$rootScope',
function($scope, $rootScope) {
var deregister = $rootScope.$on('$routeChangeSuccess', function() {
// this won't happen: we'll deregister before the event is called
$rootScope.eventLog.push({
handler: "Other",
event: e,
curr: curr,
prev: prev
});
});
$scope.$on('$destroy', function() {
deregister();
});
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>
<div ng-app="app">
<script type="text/ng-template" id="main.html">
<p>This is the content of the main template</p>
Other
</script>
<script type="text/ng-template" id="other.html">
<p>This is the content of the other template</p>
Main
</script>
<ul>
<li ng-repeat="e in eventLog track by $index">
<h3>{{e.handler}}</h3>
<pre>{{e | json:2}}</pre>
</li>
</ul>
<ng-view></ng-view>
</div>
I have these 2 controllers:
app.controller('SomeCtrl', ['$scope', '$rootScope', function($scope, $rootScope){
$scope.number = 0;
$rootScope.$on('do', function(event, data) {
$scope.number += data;
});
}]);
app.controller('SecondCtrl', ['$scope', function($scope) {
this.something = function() {
$scope.$emit('do', 5);
};
}]);
and in html I'm just writing this variable:
<div ng-controller="SomeCtrl">{{number}}</div>
When I call something function it emits the do. But it's updating the number like 10 seconds. Why?
The problem was solved by calling $scope.$apply();.
I have a controller as main controller and a its child controller. I want to execute first the main controller and then after its child controller.
I am collecting some userdata and want to keep it in $rootScope so that i could access it within the whole application.
How could i do this ?
<body ng-app="angularApp">
<div ng-controller="MainAppController">
<div ng-controller="childController">
Here i want to access data from "MainAppController" stored in $rootScope
But problem is "childController" runs before "MainAppController"
</div>
</div>
</body>
Here is the angular code
angular.module('MyApp').controller('MainAppController', function($rootScope, service){
$rootScope.userData = [];
service.getUserData().success(function(userDetails){
$rootScope.userData = userDetails;
});
});
angular.module('MyApp').controller('childController', function($scope, $rootScope){
$scope.userInfo = $rootScope.userData;
//Here $scope.userInfo is null because $rootScope.userData gets assigned to $scope.userInfo in this controller before userDetails gets assigned to $rootScope.userData in MainAppController controller.
I want that untill "$rootScope.userData = userDetails;" is not finished , "$scope.userInfo = $rootScope.userData;" must not run.
How can i do this ?
});
There are two ways i know you can do this.
1 way ::
Use $rootScope.userData directly in html and when your parent controller will run $rootScope.userData will get updated and by dual binding feature of angular, your view will get updated accordingly
Code::
//angularjs Code
var app = angular.module('MyApp', []);
app.controller('MainController', function($rootScope, $timeout) {
$rootScope.userData = {};
$timeout(function() {
$rootScope.userData = {name:'myName'};
}, 3000);
});
app.controller('childController', function() {
});
//html code
<div ng-app="MyApp" ng-controller="MainController">
<div ng-controller="childController">
{{userData.name}}
</div>
</div>
2 way::
You can attach $watch on $rootScope.userData in childController so when $rootScope.userData will get updated $watch will run and inside $watch you can update your $scope variable
Code::
//Angularjs Code
var app = angular.module('MyApp', []);
app.controller('MainController', function($rootScope, $timeout) {
$rootScope.userData = {};
$timeout(function() {
$rootScope.userData = {name:'myName'};
}, 2000);
});
app.controller('childController', function($scope, $rootScope) {
$scope.$watch(function(){
return $rootScope.userData;
}, function(){
$scope.userInfo = $rootScope.userData;
});
});
//HTML Code
<div ng-app="MyApp" ng-controller="MainController">
<div ng-controller="childController">
{{userInfo.name}}
</div>
</div>