Modify variable of parent controller inside child controller AngularJS 1.x - javascript

I have my body controlled by a MainController. In the body, I have another nested controller. In my index.html, I have a div element controlled by the nested controller:
index.html
<body ng-controller="MainController">
<div ng-controller="LoginController" ng-hide="isLoggedIn"></div>
<div class="navbar" ng-hide="!isLoggedIn">
<!-- A form which calls login() function inside LoginController -->
</div>
</body>
MainController:
angular.module('DemoApp')
.controller('MainController', ['$scope', function ($scope) {
$scope.isLoggedIn = false;
}]);
LoginController
angular.module('DemoApp')
.controller('LoginController', ['$scope', '$location', function ($scope, $location) {
$scope.login = function () {
if($scope.loginCredentials.username === 'username' && $scope.loginCredentials.password === 'password') {
$scope.parent.isLoggedIn = true; /* here, how to modify this variable */
$location.path('/home');
}
};
}]);
All I want to do is change the variables of MainController, which is isLoggedIn, from my nested controllers. I used $scope.parent, but it shows unknow provider parent. How to achieve this?

You need to use $parent to get the parent controller scope, then various methods and properties can be accessed.
$scope.$parent.isLoggedIn = true;

Related

Unable to update Child controllers scope valriable

Im new to angular js and im not able to figure out how to change the child controller scope variable from parent controller. Here is the code snippet for that:
var mainApp = angular.module("mainApp", []);
var parentCtrl = function($rootScope, $scope, shareService, $log){
shareService.setDetails($scope.pdetails);
}
var mainCtrl1 = function($rootScope, $scope, shareService, $log){
$scope.msg = "Controller 1";
$scope.details = shareService.details;//shareService.details;
}
var mainCtrl2 = function($rootScope, $scope, shareService){
$scope.msg = "Controller 2";
$scope.details = shareService.details;//shareService.details;
}
parentCtrl.$inject = ["$rootScope", "$scope", "shareService", "$log"];
mainCtrl1.$inject = ["$rootScope", "$scope", "shareService", "$log"];
mainCtrl2.$inject = ["$rootScope", "$scope", "shareService", "$log"];
mainApp.controller("parentController", parentCtrl)
.controller("mainController1", mainCtrl1)
.controller("mainController2", mainCtrl2)
.factory("shareService", function(){
var shareData = {
details : "sadfgs detaisdfadsfasdf..",
setDetails: function(value){
this.details = value;
}
};
return shareData;
});
<html>
<head>
<title>Angular JS Views</title>
<script src='lib/angular.js'></script>
<script src='js/mainApp.js'></script>
<script src='js/studentController.js'></script>
</head>
<body ng-app = 'mainApp' ng-controller='parentController' ng-strict-di>
<div ng-controller='mainController1'>
1. Msg : {{msg}}<br/>
Share Details: {{details}}<br/><br/>
</div>
<div ng-controller='mainController2'>
2. Msg : {{msg}}<br/>
Share Details: {{details}}<br/><br/>
</div>
<input type='text' ng-model='pdetails'/>
</body>
</html>
Here is the Plunker link:
https://plnkr.co/edit/hJypukqMmdHSEZMVnkDO?p=preview
In order to change value of child controller from parent controller you can use $broadcast on $scope.
syntax
$scope.$broadcast(event,data);
$broadcast is used to trigger an event(with data) to the child scope from current scope.
In child controller use $on to receive the event(with data).
Here id the code snippet:
app.controller("parentCtrl",function($scope){
$scope.OnClick=function()
{
$scope.$broadcast("senddownward",$scope.messege);
}
});
app.controller("childCtrl",function($scope){
$scope.$on("senddownward",function(event,data)
{
$scope.messege=data;
});
});
In this example I am broadcasting the event on ng-click,you can use some other custom event.like $watch on $scope.
See this example
https://plnkr.co/edit/efZ9wYS2pukE0v4JsNCC?p=preview
P.S. you can change the name of event from senddownward to whatever you want
You can access the parent's scope properties directly due to the scope inheritance:
<div ng-controller='mainController1'>
Share Details: {{pdetails}}
</div>
Your example does not work because the controllers get executed only once before the view is rendered, pdetails is empty at that moment.
To monitor the changes to pdetails, you can use $watch in the child controller:
$scope.$watch('pdetails', function(newVal) {
$scope.details = newVal;
});

Getting controller name from $parent in AngularJS

I have converted one of my Angular controllers to Controller As syntax, but I am having trouble getting an ng-grid template to play nicely.
The controller has a function called edit user that looks like this
self.editUser = function (user_data) {
var modalInstance = $modal.open({
templateUrl: '/admin/views/adminuser.html',
controller: 'AdminUserController',
resolve: {
user_data: function () {
return user_data;
}
}
});
modalInstance.result.then(function () {
self.myQueryData.refresh = !self.myQueryData.refresh;
});
};
the ng-grid template looks like this
<div class="ngCellText" ng-class="col.colIndex()">
<a ng-click="$parent.$parent.$parent.$parent.editUser({user_id:row.entity.id, first_name:row.entity.first_name, last_name:row.entity.last_name, email:row.entity.email})">
<span ng-cell-text translate>Edit</span>
</a>
</div>
and my route looks like this
.when('/admin/settings', {
templateUrl: '/admin/views/settings.html',
controller: 'SettingsController as sc',
})
So the problem is in the template when I call
$parent.$parent.$parent.$parent.editUser
it doesn't know what I am talking about unless I include the controller name like
$parent.$parent.$parent.$parent.sc.editUser,
then it works great. However I don't want to bind this template directly to the sc controller. How can I call the editUser without using the controller name?
I was hoping there would be a function on the $parent that would supply the function name like
$parent.$parent.$parent.$parent.getController().editUser
Any suggestions?
You can call functions on parent scope directly without referring to $parent. Because you might get in to trouble later when you modify your view structure.
example:
<div ng-app="MyApp">
<div ng-controller="MyController">
{{myMessage}}
<div ng-controller="MyController2">
<div ng-controller="MyController3">
<div ng-controller="MyController4">
<button id="myButton" ng-click="setMessage('second')">Press</button>
</div>
</div>
</div>
<script>
angular.module('MyApp', [])
.controller('MyController', function($scope) {
$scope.myMessage = "First";
$scope.setMessage = function(msg) {
$scope.myMessage = msg;
};
}).controller('MyController2', function($scope) {
}).controller('MyController3', function($scope) {
}).controller('MyController4', function($scope) {
});
</script>
</div>
</div>
Or else you can use angular $broadcast
Since you are using controllerAs syntax, you can address your controller by the alias, so the actual template line will look like this:
<a ng-click="sc.editUser({user_id:row.entity.id, first_name:row.entity.first_name, last_name:row.entity.last_name, email:row.entity.email})">

AngularJS not displaying scope data

I'm having issues with a dynamically placed template.
My HTML for index.html looks something like this:
<body data-ng-controller="MainController">
<data-ng-include id="outside" src="dynamicTemplate()"></data-ng-include>
</body>
The index.html page displays a template based on a certain condition.
Here is the code for my home.html, which is the default template for index.html.
<span data-ng-bind="message" data-ng-style="messageStyle"></span>
<form data-ng-controller="FormController" data-ng-submit="processForm()">
other form stuff goes here
</form>
My FormController looks something like this:
app.controller("FormController", ['$scope', '$http', '$window', function($scope, $http, $window) {
$scope.message = "";
$scope.processForm = function() {
$scope.message = "Processing form";
$scope.messageStyle = {
"color": "green"
};
// Ajax Logic to process form
.success(function(data) {
$scope.message = data.msg; /* Message never gets updated in the view */
});
};
}]);
The issue here is that the $scope.message never displays any data in the data-ng-bind="message" after the FormController gets called. I think the issue lies with the scope not knowing which controller it belongs to. How can I fix this?

How can I show hidden div with angularjs by url

How do I access the page below and show the div CertificateRegister instead of div EmailRegister via URL, for example www.mysite.com/register#CertificateRegister
eAssinatura.controller('CadastroController', ['$scope', '$route', '$routeParams', '$location', '$http', '$modal', 'blockService', 'notifyService', 'browserService', 'locale',
function ($scope, $route, $routeParams, $location, $http, $modal, blockService, notifyService, browserService, locale) {
//$scope.EmailRegister = true; // setting the div register by e-mail visible when the page loads
//$scope.CertificateRegister = false;
//$scope.showEmailRegister = function () {
// $scope.EmailRegister = true;
// $scope.CertificateRegister = false;
//};
//$scope.showCertificateRegister = function () {
// if (!$scope.LoadedPKI) { //setting PKI when register by certificate is selected
// init();
// }
// $scope.EmailRegister = false;
// $scope.CertificateRegister = true;
//};
$scope.RegisterDisplay = false;
if ($location.path() == '/CertificateRegister') {
$scope.RegisterDisplay = true;
}
}
]);
<div ng-show="RegisterDisplay">
<p>E-mail Register</p>
Don' t Have Digital Certificate »
</div>
<div ng-hide="RegisterDisplay">
<p>Certificate Register</p>
Have Digital Certificate »
</div>
At the top of your controller you can:
$scope.RegisterDisplay = false;
if ($location.path() == '/CertificateRegister') {
$scope.RegisterDisplay = true;
}
In your html you should be able to do something like this:
<div id="certregister" ng-show="RegisterDisplay">//This is your CertificateRegister div</div>
<div id="EmailRegister" ng-hide="RegisterDisplay">//This is your EmailRegister div</div>
I would try adding url variable in your route then have controller watch for that and show/hide div
If you are using ui-router you can add an optional parameter to the state, and take that parameter in your controller using the $stateProvider like this example
You probably would do something like:
$stateProvider
.state('register', {
url: "/register/:emailRegister",
templateUrl: '.html',
controller: function ($stateParams) {
// If we got here from a url of /register/true
if($stateParams.emailRegister){
$scope.showCertificateRegister();
}
}
})
Are you using $routeProvider for routing?
If so, you can create a parameter and read it in your controller.
route:
$routeProvider.when('/register/:showParam?', {...});
controller:
if ($route.current.params.showParam === 'CertificateRegister') {
$scope.CertificateRegister = true;
}
*I you should add some validations (undefined, toLowerCase)

How to retrive a $scope value outside the function it is defined, in Angular JS

I have the Controller
function loginController($scope, $http, $cookieStore, $location) {
var token = $cookieStore.get('token');
var conId = $cookieStore.get('Cont_Id');
var exId = $cookieStore.get('ex_Id');
$scope.log_me = function() {
$scope.login_me = [];
var login_un = $scope.uservals;
var login_pwd = $scope.passvals;
var logs_me = "api call here";
$http.get(logs_me)
.success(function(response) {
$cookieStore.put('token', response.token);
$cookieStore.put('ex_Id', response.ExId);
$cookieStore.put('Cont_Id', response.contactId);
$cookieStore.put('email', response.email);
$cookieStore.put('name', response.name);
$scope.log_sess = response;
$scope.sess_id= response.ss_id;
alert($scope.sess_id);
if (response.status == "failure, invalid username or password") {
$('.login_error').show();
$('.login_error').html('Invalid username or password');
$('.login_error').delay(4000).fadeOut();
$('.loading').hide();
} else {
$location.path('/dashboard');
}
});
}
}
I have used the above controller in my login page and it is working fine. Now i want to use the same controller in another template and retrieve the value "$scope.sess_id"
My Template is
<div class="page" >
<style>
#report_loader object {
width: 100%;
min-height: 700px;
width:100%;
height:100%;
}
</style>
<div class="loading"> </div>
<section class="panel panel-default" data-ng-controller="loginController">
<div class="panel-body" style=" position: relative;">
<div id="report_loader" style="min-height:600px;">
{{sess_id}}
<script type="text/javascript">
$("#report_loader").html('<object data="https://sampleurl/contact/reports/members/sorted_list.html?ss_id=' + sess_id+' />');
</script>
</div>
</div>
</section>
</div>
I am unable to retrieve the value {{sess_id}} here. What should be done so that i can bring this value in my template
You're routing the user to the "dashboard" route upon successful log in. Even though it might feel like you're using the same "loginController" for both login and dashboard, it will be an entirely new instance of both the controller and $scope. Which is why the {{sess_id}} is not displaying on the dashboard template.
If you're following an MVC-like pattern of AngularJS, ideally you want to be creating a new controller for your dashboard template. See explanation: https://docs.angularjs.org/guide/controller#using-controllers-correctly
So, I would create a DashboardCtrl and share the sess_id between the two. There are plenty of examples out there of how to share data between controllers:
You can use a factory: Share data between AngularJS controllers
You can use $rootScope: How do I use $rootScope in Angular to store variables?
Hope it helps.
I would use the rootScope approach, but an easier way to do that is to simply create a 'global' variable.
In your main controller (not your login controller), define a global scope variable like this:
$scope.global = {};
Then in your login controller, modify your session id to use the global variable:
$scope.global.sess_id= response.ss_id;
alert($scope.global.sess_id);
Then in your html:
<div id="report_loader" style="min-height:600px;">
{{global.sess_id}}
It's simple and works like champ.
I would create a service :
services.sessionService = function(){
var sessionID = null;
this.setSessionID = function(id){
sessionID = id;
}
this.getSessionID = function(){
return sessionID;
}
}
then in your controller :
$scope.sess_id= response.ss_id;
alert($scope.sess_id);
sessionService.setSessionID( $scope.sess_id );
and in your dashboard controller :
$scope.sess_id = sessionService.getSessionID();
Approaches
Your question's answer has many approach. They are:
Using value or service, you can call it wherever your controllers need them.
Using $rootScope, this is very common and easy to use. Just define your $rootScope inside your main controller or whatever controller that called first and then you can call it from other controllers like any $scope behavior.
Using $controller service or usually called controller inheritance. Define this in controller function's parameter, then type $controller('ControllerNameThatIWantToInheritance', {$scope:$scope});
Maybe any other approach can be use to it. Each of them have strength and weakness.
Examples:
using value
.value('MyValue', {
key: null
})
.controller('MyCtrl', function ($scope, MyValue) {
$scope.myValue = MyValue;
})
you can modified MyValue from service too
using $rootScope
.controller('FirstCtrl', function ($scope, $rootScope) {
$rootScope.key = 'Hello world!';
})
.controller('SecondCtrl', function ($scope, $rootScope) {
console.log($rootScope.key);
})
will print 'Hello World', you can also use it in view <div>{{key}}</div>
using $controller
.controller('FirstCtrl', function ($scope) {
$scope.key = 'Hello world!';
})
.controller('SecondCtrl', function ($scope, $controller) {
$controller('FirstCtrl', {$scope:$scope});
})
Second controller will have $scope like first controller.
Conclusion
In your problem, you can split your controller for convenient. But if you dont' want to, try to define $scope.sess_id first. It will tell the Angular that your sess_id is a defined model, and angular will watch them (if you not define it first, it will be 'undefined' and will be ignored).
function loginController($scope, $http, $cookieStore, $location) {
var token = $cookieStore.get('token');
var conId = $cookieStore.get('Cont_Id');
var exId = $cookieStore.get('ex_Id');
$scope.sess_id = null //<- add this
$scope.log_me = function() {
$scope.login_me = [];
var login_un = $scope.uservals;
var login_pwd = $scope.passvals;
var logs_me = "api call here";
$http.get(logs_me)
.success(function(response) {
$cookieStore.put('token', response.token);
$cookieStore.put('ex_Id', response.ExId);
$cookieStore.put('Cont_Id', response.contactId);
$cookieStore.put('email', response.email);
$cookieStore.put('name', response.name);
$scope.log_sess = response;
$scope.sess_id= response.ss_id;
alert($scope.sess_id);
if (response.status == "failure, invalid username or password") {
$('.login_error').show();
$('.login_error').html('Invalid username or password');
$('.login_error').delay(4000).fadeOut();
$('.loading').hide();
} else {
$location.path('/dashboard');
}
});
}
}

Categories

Resources