I have two controllers like this
<div ng-controller="ParentController">
<div ng-controller="ChildController">
... my grid table ..
</div>
</div>
js code
function ParentController($scope) {
...
$scope.refreshBtnClicked = function() {
//here I want to call refreshGrid method of ChildController
}
}
function ChildController($scope) {
...
$scope.refreshGrid = function() {
... its using some inner variables of Child controller...
}
}
How can I call it?
Try this way, you will have to implement your service function but that's basically grid stuff.
<div ng-controller="ParentController">
<div ng-controller="ChildController">
... my grid table ..
</div>
</div>
function ParentController($scope, gridService) {
...
$scope.refreshBtnClicked = gridService.refresh();
}
function ChildController($scope, gridService) {
...
do whatever you like with your gridService methods or properties.
}
your factory or service
angular.module('myApp')
.service('Gridservice', function Gridservice() {
//data and methods here
});
you can also use broadcast or emit to trigger events, between controllers. like if you refresh, also your childcontroller data gets updated.
With directives, you can "register" the child controller or scope in the parent. Something like this:
app.directive('parent', function(){
controller: function(){
this.children = [];
this.addChild = function(childScope){
this.children.push(childScope);
}
this.callChildFunc = function(childID){
children[childID].someFunc();
}
};
})
app.directive('child', function(){
require: '^parent',
link: (scope, elem, attrs, parentCtrl) {
parentCtrl.addChild(scope)
scope.someFunc = function(){};
}
})
The child calls a function that adds a reference to its scope in the parent so it can call its functions. Another option would be to use $scope instead of this in the parent's controller and pass the addChild function to the child's scope using an isolate scope.
Well, you would have to do these things the AngularJS way. If there is a method or idea you want to share across controllers, you should implement it as a factory or service. And then you can use emit or broadcast to simultaneously share this service between controllers.
Can one controller call another?
Related
I have a button where I am passing the ng-model value as a parameter to its ng-click function, Now after this ng-click function executes, I would like to send that ng-model value to another controller, how can I do this using angular?
Is there a way to do this?
There are many ways to communicate between controllers.
use $broadcast like mentioned in other comments, or
use $emit
Something like this...
function Controller1($scope)
{
$scope.$on('myEvent', function(event, args) {
// do the event
});
// another controller, directive
}
function Controller2($scope)
{
$scope.$emit('myEvent', args);
}
1.In first Controller, you can do:
$rootScope.$broadcast('eventName', value);
and listen to the event in second Controller:
$scope.$on('eventName', function (event, value) {//your code});
2.In first controller assign the values to the $rootScope variable then access from the other controller.for example
in first controller
$rootScope.TestValue="10";
in second controller
$scope.receiveValue=$rootScope.TestValue;
3.AngularJS- How to pass data from one controller to another on ng-click()?
Use angular service to communicate between 2 controller.
Watch this Video
Yes $broadcast will work for you.
Here are some essential parts:
Create service that implements message bus functionality (e.g. $scope instance)
Inject service to both controllers
$broadcast() event from one controller
subscribe to event with $on() in another
Example:
HTML
<div ng-controller="ctrl1 as ctrl1">
<button ng-click="ctrl1.hello()">Say hello</button>
</div>
<div ng-controller="ctrl2 as ctrl2">{{ctrl2.messages}}</div>
JavaScript
angular.module('app', [])
.service('messageBus', ['$rootScope', function($rootScope) {
return $rootScope.$new();
}])
.controller('ctrl1', ['messageBus', function(messageBus) {
this.hello = function() {
messageBus.$broadcast('hello', 'Hi! '); // <= send message
}
}])
.controller('ctrl2', ['messageBus', function(messageBus) {
var ctrl2 = this;
this.messages = '';
console.log(messageBus.mb)
messageBus.$on('hello', function(evt, msg) { // <= receive message
ctrl2.messages += msg;
});
}]);
I have an application with some controllers that have the same functions as: InitMenu, GetData, Search, Paging, ..
How can I build a generic controller with the main functions: InitMenu, GetData, Search, Paging, .. without having to write in each specific controller?
share all the common logic inside a service and inject it inside your controllers.
.service('CommonData, function(){
this.getData = function(){
}
this.InitMenu= function(){
}
this.search= function(){
}
})
otherwise you can make a parent controller and all the child controllers will prototype inherit from the parent scope.
.controller('ParentCtrl', function($scope){
$scope.myObj = {};
$scope.parentMethod = function(){
return myObj;
}
})
.controller('ChildCtrl', function($scope){
var stuff = $scope.parentMethod();
//you can access the parent method in the child template as well
})
<div ng-controller="ParentCtrl">
<div ng-controller="ChildCtrl">
{{parentMethod()}}
//if you use controllAs syntax change it to {{parentCtrlName.parentMethod()}}
</div>
</div>
if you use controllerAs syntax you can access the parent $scope by specifyng the controller name as a scope field in the child controller. e.g $scope.parentCtrlName.parentMethod() and parentCtrlname.parentMethod() in the child template.
While loading I am calling one controller, however I am using ng-include to import another HTML page in the main HTML page.
I want to call ng-controller of included page.(How to call a child controller from a parent controller using ng-init)
You need not call it seperately. Just add 'ng-controller' directive on the 'ng-include' element and assign its controller as shown below:
<div ng-include="template.url" ng-controller="YourController"></div>
The best way to do this is to have the parent Controller broadcast an event that the child scope will register:
.controller("ControllerParent", [$scope, function($scope) {
$scope.alertChild = function() {
$scope.$broadcast("custom-event", data);
};
});
.controller("ControllerChild", [$scope, function($scope) {
$scope.$on("custom-event", function(event, data) {
//do something with event
};
});
I'm trying to figure out how to make a child directive communicate with it's parent directive
I basically have this html markup
<myPanel>
<myData dataId={{dataId}}></myData>
</myPanel>
In the myData directive, if there is no data available, I want to hide the myPanel.
In the myData directive controller I've tried
$scope.$emit('HideParent');
And in the myPanel controller I've tried
$scope.$on('HideParent', function () { $scope.hide = true; });
And also
$scope.$watch('HideParent', function () { if (value) { $scope.hide = true; }});
In either situation, the myPanel directive isn't receiving the $emit
You may create controller in myPanel directive.
Then require this controller in myData directive. And when child directive has no data, call controller method to hide parent.
For example in you parent (myPanel) directive:
controller: function($scope, $element){
$scope.show = true;
this.hidePanel = function(){
$scope.show = false;
}
}
In myData directive require this controller:
require:'^myPanel'
And then, call controller function when you need
if (!scope.data){
myPanelCtrl.hidePanel();
}
Look this Plunker example
The answers above where the parent directive's controller is required is a great one if there truly is a dependency. I had a similar problem to solve, but wanted to use the child directive within multiple parent directives or even without a parent directive, so here's what I did.
Your HTML.
<myPanel>
<myData dataId={{dataId}}></myData>
</myPanel>
In your directive simply watch for changes to the attribute.
controller: function ($scope, $element, $attrs) {
$attrs.$observe('dataId', function(dataId) { $scope.hide = true; } );
}
It's explicit and simple without forcing a dependency relationship where one may not exist. Hope this helps some people.
So, we have a directive grid, which exposes directive controller to the angular controller, so that controller can call functions on directive (just like a form controller).
Now, in my angular controller every thing works as long as I access the directive controller from a callback action eg. some $scope.xx which are called on some event like click or any thing.
But when i try to access the directive controller at controller initialization time, the directive controller is undefined, that means, directives link function is not called yet.
Here's some code
function controller() {
$scope.init = function() {
$scope.grid.search(xx)
}
$scope.init() // this will fail, because $scope.grid is undefined.
$scope.onClick = function() {
$scope.grid.search(xx) // this will work
}
}
is there any other way, other then watching the $scope.grid, to have the $scope.grid.search called on controller initialization
You can just broadcast event from link function in your directive.
<div ng-controller="MyCtrl">
<div abc></div>
</div>
myApp.directive('abc', function($rootScope) {
return {
restrict: "EA",
link: function(scope, element, attrs){
$rootScope.$broadcast("initialize");
}
}
});
function MyCtrl($scope) {
$scope.$on("initialize", function(){
alert("Link function has been initialized!");
});
}
I've created JSFiddle for you.
The problem is that parent controllers are always called before child controllers.
If you want to run code after your child directive is initialized, you can create a directive and put the initialization code inside of its link function.
This works because parent link functions are always called after child link (and controller) functions.