how to call parent method with dependencies in angularjs - angularjs

I am trying to use div with ng-click for routing:
ng-click="go('/item/{{item.id}}').
I can call $parent.go or even go when using ParentCtrl. But ParentCtrl_2 does not work at all. I tried to look for some answers, but can't figure it out. What am I missing?
app.controller('ParentCtrl', function($scope) {
$scope.go = function(path) {
console.log(path);
}
}
);
app.controller('ParentCtrl_2', ['$scope', '$location',
function($scope, $location) {
$scope.go = function(path) {
$location.path(path);
}
}
]);
app.controller('ChildCtrl', ['$scope', '$routeParams',
function($scope, $routeParams) {
...
}
]);

There are number of unanswered questions here but, like what is the structure of your html ng-controller structure.
Also the call sytax in html is wrong for
ng-click="go('/item/{{item.id}}')
It should be
ng-click="go('/item/'+ item.id)"
Said that depending on where the ng-click is declared it would have access to parent methods. If you can access a method using $parent then you can access the method directly due to prototypal inheritance.
If structure is like
<div ng-controller='ParentCtrl'>
<div ng-controller='ParentCtrl_2'>
<div ng-controller='ChildCtrl'>
<!-- ng-click somewhere here -->
</div>
</div>
</div>
Then you access the ParentCtrl_2 method go whenever you call.
If it is
<div ng-controller='ParentCtrl'>
<div ng-controller='ParentCtrl_2'>
</div>
<div ng-controller='ChildCtrl'>
<!-- ng-click somewhere here -->
</div>
</div>
Then you have access to ParentCtrl method go method only.

Related

Cannot read property 'nid' of undefined, need to pass object to another controller

I'm having issues trying to pass a selected value from one controller to another controller.
View (I pass the NgValue to $scope in Controller).
<li class="list-group-item" ng-repeat="item in filterData = (informes | filter:{title:searchTitle, resolucion:searchReso, year: searchYear}) | limitTo:10:10*(currentPage-1)">
<div class="wrapper">
<div class="informes" ng-value="nodeID(item)">
<a ng-href="../node-informes/node-informes.html">
<p class="text-center text-truncate">
<small>{{item.title}}</small>
</p>
</a>
</div>
</div>
</li>
Controller. I have the "Item in that Controller" and the console prints it.
informes.controller('InformesCtrl', ['drupal', '$rootScope', '$scope', '$http', 'InformesFtry', function(drupal, $rootScope, $scope, $http, InformesFtry) {
$rootScope.getData = function(informes){
$rootScope.nodeID = function(item){
$rootScope.node = item.nid;
console.log($rootScope.node);
};
}
}]);
2nd Controller in another module (gives me "Cannot read property 'nid' of undefined" error").
nodeInformes.controller('NodeInformesCtrl', ['$rootScope', '$scope', '$http', '$controller', function($rootScope, $scope, $http, $controller) {
$controller('InformesCtrl', {$scope: $scope});
$rootScope.getData(informes);
$rootScope.nodeID(item);
$scope.node = $rootScope.node;
console.log($scope.node);
}]);
It supposed that i called the other controller with parameters (saved value in "$rootScope.node", passed it to 2nd controller, but it gives me the error that's undefined).
consolelog in first controller works, but not in second controller.
I appreciate any suggestion.
Modified as code suggested, but seems that the "item" object is not passing the right way.
Try to avoid using $rootScope unless you absolutely have to (raising or handling events is about the only time I've ever used $rootScope) - instead you can use a service to reliably pass data between controllers. In AngularJS services are singletons so all of your controllers have access to the same instance. You can take advantage of this and use the service to "pass" (more accurately share) data between controllers.
Here is a simple example to demonstrate the concept which you can then apply to your situation. Normally you wouldn't have two controllers in a single view like this, but for illustration purposes (and being able to run in the SO snippet engine) I've done it here. Just to prove that I'm not sharing any controller variables I've named them differently.
angular.module('app', [])
.service('sharedService', function() {
var service = {};
service.sharedObject = {};
service.sharedObject.value = "Set in service";
return service;
})
.controller('ctrlOne', function($scope, sharedService) {
$scope.sharedObjectC1 = sharedService.sharedObject;
})
.controller('ctrlTwo', function($scope, sharedService) {
$scope.sharedObjectC2 = sharedService.sharedObject;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="ctrlOne" style="margin-bottom: 30px;">
<h1>Controller One</h1>
Modifying this value will update it in Controller Two:
<div>
<input ng-model="sharedObjectC1.value" />
</div>
</div>
<hr>
<div ng-controller="ctrlTwo">
<h1>Controller Two</h1>
Modifying this value will update it in Controller One:
<div>
<input ng-model="sharedObjectC2.value" />
</div>
</div>
</div>

Is it possible to call a function of outer AngularJS controller on page?

Let's say controller named cOne has a function
function showAlert() {
alert("Hello, people!");
}
And I have a situation like shown below
<div id='parent' ng-controller='cOne'>
<span ng-click='cOne.showAlert()'>Click For Alert</span>
<div id='child' ng-controller='cTwo'>
<span ng-click='$parent.cOne.showAlert()'>Click For Parent Controller Alert </span>
</div>
</div>
Can I somehow call the function of that cOne controller from the "child" div? I tried to use $scope, $rootScope and $parent. How do I do it right?
You just need to assign showAlert to $scope of cOne controller., and from child just call via $parent.
angular.module('myApp', [])
.controller('cOne', function($scope) {
$scope.showAlert = function() {
alert('cOne alert');
};
})
.controller('cTwo', function($scope) {});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="cOne">
<span ng-click='showAlert()'>Click For Alert-1</span>
<div ng-controller="cTwo">
<span ng-click='$parent.showAlert()'>Click For Alert-2</span>
</div>
</div>
You should bind your function to either scope or controller instance. If it is bound to scope
$scope.showAlert = function () {
alert("Hello, people!");
}
you'll be able to call it like
<span ng-click='$parent.showAlert()'>Click For Parent Controller Alert </span>
If you bind it to controller instance, you'll be able to call it in a way, you've just posted.

How to pass scope variable through ng-click function?

Here when i click on cartDetails the dynamic scope variable x.SmId value need to be passed to the bellow function and in alert box need to display the parameter .How can we do this one in angular js?
<div ng-app="" ng-controller="MyCtrl">
<div ng-repeat="x in names">
<div ng-click="cartDetails('{{x.SmId}}')">
<div>{{x.name}}</div>
</div>
</div>
</div>
<script>
angular.module('MyApp', [])
.controller('MyCtrl', ['$scope', '$http', function($scope, $http) {
$scope.search = function(param) {
$http.get('AngularJs-Response.jsp?mid='+param).success(function(response) {
$scope.names = response;
});
};
$scope.cartDetails = function(smid) {
alert(smid);
};
}]);
</script>
Use simple:-
ng-click="cartDetails(x.SmId)"
I tried to use:
ng-click="cartDetails(x.SmId)"
but it simply x.SmId as string, its not replaced by value. After reading few more articles, I found a solution like below:
<div ng-click="cartDetails('{{x.SmId}}')">
Its a working solution in AngularJS v1.3.9

difference between init function calling from controller initialization and from html page at rendering in angular js

what is the difference between init() method calling from controller initialization time and from html page at rendering in angular js ?
html partial:
<div ng-init="init()">
---
---
</div>
controller :
angular.module('masterJs')
.controller('SignupCtrl', function ($scope, $rootScope) {
$scope.init(){
//code here
}
});
here i am calling init() method from partial. what is the difference when we call init() from controller not from the html page like:
angular.module('masterJs')
.controller('SignupCtrl', function ($scope, $rootScope) {
$scope.init(){
//code here
}
$scope.init();
});
The difference is that when you have the ng-init in the HTML, the init() function will only be called during the actual render of the page. If for any reason that content needs to be re-rendered, the init() function will be called again.
When you call the init() function on the controller, it will only run one time (when the controller is created). According to angular's documentation, this is the best practice (avoid using ng-init).
Normally you use ng-init for intitializing a ng-repeat.
The only appropriate use of ngInit is for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
Example:
<script>
angular.module('initExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.list = [['a', 'b'], ['c', 'd']];
}]);
</script>
<div ng-controller="ExampleController">
<div ng-repeat="innerList in list" ng-init="outerIndex = $index">
<div ng-repeat="value in innerList" ng-init="innerIndex = $index">
<span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
</div>
</div>
</div>
The way you are using the init function, is inappropriate.

Angularjs DOM is refreshed but screen is not redrawing. Not sure where to go from here

I am having a very troubling problem where ng-click updates the expected scope variables, the scope variables appear to change on the DOM ( when viewed via the chrome debugger) but the dom elements that have changed are not redrawn in the browser. I have noticed across multiple browsers and devices BUT ONLY WHEN THE SCREEN WIDTH IS BELOW 768. I am using angular version 1.2.6. Has anyone come across this type of issue??
I have simplified the code to try to isolate and confirm what is happening. Here is the code in its simplified version:
First the view:
<section class="stream-area">
<div class="group">
<div class="gw-fixed-top-panel">
<div class="group-heading ">
<div class="panel-title">
<span class="fleft name" ng-click="usergroup.collapsed=!usergroup.collapsed"> CLICK HERE </span>
<a ng-show="usergroup.collapsed" title="Click to edit group" ><i class="fa fa-cog"></i></a>
<a ng-hide="usergroup.collapsed" title="Click to edit group" ><i class="fa fa-chevron-up"></i></a>
<div> {{usergroup.collapsed}}</div>
</div>
</div>
</div>
</div>
</section>
The controller does nothing at this point...
'use strict';
(function () {
var groupController = function($scope) {
$scope.usergroup={};
$scope.usergroup.collapsed=true;
};
myOverall.myApp.controller('GroupController',['$scope', groupController]);
}());
The controller is invoked by via .config:
(function () {
golfWire.gwWebApp =angular.module('gwWebApp', [
'ngRoute',
'ngAnimate',
'ngResource',
'ui.bootstrap',
'firebase',
'LocalStorageModule',
'ngGrid'
]);
myOverall.myApp
.config(['$routeProvider','$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
.when('/group/view', {
controller: 'GroupController',
templateUrl: '/app/views/group.html'
})
.otherwise({
redirectTo: '/main'
});
/* $locationProvider.html5Mode(true); */
}]);
Add this function in your controller
$scope.toggleUserGroup = function(){
$scope.usergroup.collapsed = ! $scope.usergroup.collapsed;
$scope.$apply();
}
Call this function on ng-click. This should get the DOM updated and refreshed.
Reasoning: By calling $apply() you trigger a digest() cycle, which checks for changed expression and repaints the DOM if need be.
Incase this doesn't fix the issue, please provide a plunkr/fiddle. Would be happy to get some working code.
Thanks,
A slight variation on Eliel's answer in AngularJS - bind to directive resize worked for me. In the directive.js:
$scope.onResizeFunction = function() {
};
// Call to the function when the page is first loaded
$scope.onResizeFunction();
angular.element($(window)).bind('resize', function() {
$scope.onResizeFunction();
$scope.$apply();
});
I call
$(window).resize();
from within my app.js. The directive's d3 chart now resizes to fill the container.

Resources