Unable to update Child controllers scope valriable - javascript

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;
});

Related

$scope returns undefined in ionic app

I am wondering at the dual behaviour of $scope. In the below script I am getting value of name as alert. But in my ionic app the same code alerts undefined.
I googled the problem and found this link as a solution where it states that we need to use dot(.) in order to get the value in ng-model. What is the difference between two.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.a =function a(){alert($scope.name);}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
Name: <input ng-model="name" ng-blur="a()">
</div>
Try changing your controller function as below:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.a =function(){
alert($scope.name);
}
});
Actually it does work with Ionic,
angular.module('starter.controllers', [])
.controller('myCtrl', function($scope) {
$scope.a = function a() {
alert($scope.name);
}
})
DEMO
Solution :
"If you use ng-model, you have to have a dot in there."
Make your model point to an object.property and you'll be good to go.
Controller
$scope.formData = {};
$scope.check = function () {
console.log($scope.formData.searchText.$modelValue); //works
}
Template
<input ng-model="formData.searchText"/>
<button ng-click="check()">Check!</button>
This happens when child scopes are in play - like child routes or ng-repeats.
The child-scope creates it's own value and a name conflict is born as illustrated here:
See this video clip for more: https://www.youtube.com/watch?v=SBwoFkRjZvE&t=3m15s
.
And that is referred from below links :
Other Solutions
Use this keyword instead of $scope, More details
And also you can get more details from this below two discussions
Ng-model does not update controller value
Why is my ng-model variable undefined in controller?
Update Solution 1 :
Please declaring the blank object first at the top of your controller:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.name = "";
$scope.a = function(){alert($scope.name);}
});
I hope these will be helps to you.
Try to use json object.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.user = {'name':''};
$scope.a =function a(){alert($scope.user.name);}
});
<div ng-app="myApp" ng-controller="myCtrl">
Name: <input ng-model="user.name" ng-blur="a()">
</div>

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

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;

Scope true in directive giving wrong result

I am using scope as 'true' in a directive. So now, this directive scope passes from parent to child, but not in reverse. I am printing now scope.name 2 times. First in parent scope, second in directive. Now I should get 2 different values. But, I am getting same scope value for both. Pl help explain!
//module declaration
var app = angular.module('myApp',[]);
//controller declaration
app.controller('myCtrl',function($scope){
$scope.name = "Peter";
});
//app declaration
app.directive('myStudent',function(){
return{
template: "{{name}}",
scope:true
}
controller: [function(){
$scope.name = "Roger"
}]
});
<body ng-app="myApp" ng-controller="myCtrl">
{{name}},
<my-student></my-student>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular.min.js"></script>
Your controller is out of directive. I placed it inside and added $scope dependency. It works!
//module declaration
var app = angular.module('myApp',[]);
//controller declaration
app.controller('myCtrl',function($scope){
$scope.name = "Peter";
});
//app declaration
app.directive('myStudent',function(){
return{
template: "{{name}}",
scope:true,
controller: ['$scope', function($scope) {
$scope.name = "Roger"
}]
}
});
<body ng-app="myApp" ng-controller="myCtrl">
{{name}},
<my-student></my-student>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular.min.js"></script>
Write your controller inside of DDO.
//app declaration
app.directive('myStudent',function(){
return{
template: "{{name}}",
scope:true,
controller: ['$scope', function($scope){
$scope.name = "Roger"
}]
}
Probably, this will solve your problem.
Easy make an object in parent controller so that it can be binded with directive
i.e var x={};
x.value=value;// that you want to pass then try accessing it.

How to add multiple controller in single page in AngularJS

I am new to AngularJS I have a problem with this code. I want to add multiple controller in single ng-app. But it execute first one. Why not second one?
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angul /1.4.8/angular.min.js"></script>
</head>
<body>
<div ng-controller="cont1">
<input type="text" ng-model="fullname">
{{fullname}}
</div>
<div ng-controller="cont2">
<input type="text" ng-model="fname">
{{fname}}
</div>
<script>
var app = angular.module("myapp", []);
app.controller('cont1', function ($scope) {
$scope.fullname = "";
});
var new = angular.module('myapp', []);
new.controller('cont2', function ($scope) {
$scope.fname = "";
});
</script>
</body>
</html>
Because you are overwriting the first myapp module when you do var new= angular.module('myapp',[]);.
Your code should be:
var app = angular.module("myapp", []);
app.controller('cont1', function($scope) {
$scope.fullname = "";
});
app.controller('cont2', function($scope) {
$scope.fname = "";
});
or
var app = angular.module("myapp", []);
app.controller('cont1', function($scope) {
$scope.fullname = "";
});
angular.module("myapp").controller('cont2', function($scope) {
$scope.fname = "";
});
The second parameter[] passed to module() makes the difference
To best way to define controllers, directives, factories etc... is
define your modules names in a separate file
app.module.js
angular.module("myapp",[]); // inside [] you define your module dependencies
for controllers create separate file (depending on your requirement even you can create 1 file for 1 controller)
some.controller.js
angular.module("myapp").controller('someCtrl'['$scope', function($scope){
}]);
angular.module("myapp").controller('someOtherCtrl'['$scope', function($scope){
}]);
NOTE:
Two types you can write controller
TYPE1 (not recomended)
.controller('ctrlName', function($scope){
});
TYPE2 (recomended)
.controller('ctrlName', ['$scope', function($scope){
}]);
Reason
So as you can see in the TYPE2 we are passing controller dependencies in an array, so when we compile our program angular will give the name as eg:a to $scope inside function() and treat it as $scope.
With the TYPE1 you need to follow specific order while defining controller dependency otherwise angular will through error because in this approach angular simply treats first dependency as $rootscope, second as $scope and so on....
For Eg:
you can't pass dependencies to your controller like this
.controller('ctrlName', function($http, $scope) {
});
this will throw error
if you define like
.controller('ctrlName', function($scope, $http) {
});
this will work fine since its in order that angular wants.
You can define multiple controllers in a single module in this way also:
angular.module("myapp",[]);
.controller('cont1',function($scope){
$scope.fullname="";
});
.controller('cont2',function($scope){
$scope.fname="";
});
When you are defining modules, don't use var. You can find some of the Angular best practices here: Angular Style Guide/Best Practices

Update a service value from a parent controller

I've been searching for hours how to update a service value from a nested controller.
My child controller needs to update a value in a service. And that value needs to be shown in the parent controller.
I've made a jsfiddle to make it more clear and easy to help
http://jsfiddle.net/jtsmduxw/3/
<body ng-app="MyApp">
<div ng-controller="parentCtrl">
<p>{{username}}</p>
<div ng-controller="childCtrl">
<p>{{username}}</p>
</div>
</div>
</body>
-
var app = angular.module("MyApp", []);
app.service('authenticationSrv', function () {
var user = 'anonymous';
return {
getUser: function () {
return user;
},
setUser: function (value) {
user = value;
}
};
});
app.controller("parentCtrl", function ($scope, authenticationSrv) {
$scope.username = authenticationSrv.getUser();
});
app.controller("childCtrl", function ($scope, authenticationSrv) {
authenticationSrv.setUser('my name'); // I need this function to also update the scope of the parent
$scope.username = authenticationSrv.getUser();
});
(I've read and tried Update parent scope variable, but I could not make it work with the service.)
Thanks!
Make use of an object literal instead of the variable username.
Parent
app.controller("parentCtrl", function ($scope, authenticationSrv) {
$scope.parentObject = {};
$scope.parentObject.username = authenticationSrv.getUser();
});
Child
app.controller("childCtrl", function ($scope, authenticationSrv) {
authenticationSrv.setUser('my name');
$scope.parentObject.username = authenticationSrv.getUser();
});
Working Example
var app = angular.module("MyApp", []);
app.service('authenticationSrv', function () {
var user = 'anonymous';
return {
getUser: function () {
return user;
},
setUser: function (value) {
user = value;
}
};
});
app.controller("parentCtrl", function ($scope, authenticationSrv) {
$scope.parentObject = {};
$scope.parentObject.username = authenticationSrv.getUser();
});
app.controller("childCtrl", function ($scope, authenticationSrv) {
authenticationSrv.setUser('my name');
$scope.parentObject.username = authenticationSrv.getUser();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="MyApp">
<div ng-controller="parentCtrl">
<p>{{parentObject.username}}</p>
<div ng-controller="childCtrl">
<p>{{parentObject.username}}</p>
</div>
</div>
</body>
Make user in the Service an object instead of a primitive (string). Then use {{user.name}} in your view.
Notice that I did some minor changes to authenticationSrv.setUser()
and renamed it to authenticationSrv.setUserName().
See my working fiddle: https://jsfiddle.net/rbwk3rqb/
var app = angular.module("MyApp", []);
angular.module("MyApp")
.service('authenticationSrv', function () {
var user = {name: 'anonymous'};
return {
getUser: function () {
return user;
},
setUserName: function (value) {
user.name = value;
}
};
});
angular.module("MyApp")
.controller("parentCtrl", function ($scope, authenticationSrv) {
$scope.user = authenticationSrv.getUser();
});
angular.module("MyApp")
.controller("childCtrl", function ($scope, authenticationSrv) {
authenticationSrv.setUserName('my name');
$scope.user = authenticationSrv.getUser();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="MyApp">
<div ng-controller="parentCtrl">
<p>{{user.name}}</p>
<div ng-controller="childCtrl">
<p>{{user.name}}</p>
</div>
</div>
</body>
As user is a primitive value in the service, when you put the value from the service to your controller's scope with this line:
$scope.username = authenticationSrv.getUser();
the value of user is copied into $scope.username. So just because later on you overwrite the value of user in the service, nothing is changing in your "parent" $scope.
There are several ways to get around this, the easiest is probably to create a user object in your service - if you store the reference to this object in your scopes, it will reflect the changes made to it from other controllers. (Objects in javascript are passed by reference value, so all controllers will be affecting the same object, not copies of the values.) For the actual implementation, I'd guide you back to the same link you posted - when you tried implementing that, what was the problem with it? Show us the code you tried.
Alternatively, you can also implement the observer pattern using this service (this is considerably more work), or use events on the scope hierarchy to notify the controllers of the change of user (this is a questionable practice).
The idea is to create and object to update and not just a primitive:
$scope.user = {};
$scope.user.name = authenticateSrv.getUser();
and in the child scope you just set it:
$scope.user.name = authenticateSrv.setUser('my name');
here is a Fiddle

Categories

Resources