$rootScope changed doesn't reflect on template - angularjs

I'm a newbie in angularjs. I'm trying to build a simple app which contain login page and dashbboard page.
Now, I got a problem with updating html template when rootScope changed.
Here is my component template :
<!-- show dashboard page app >
<div layout="column">
<div ng-show="$rootScope.isAuthenticated">
<pm-header></pm-header>
<div layout="row">
<pm-sidebar></pm-sidebar>
<div layout="column" class="sitecontent" layout-padding>
<md-content ui-view></md-content>
</div>
</div>
</div>
<!-- show login page app >
<div ng-hide="$rootScope.isAuthenticated">
<pm-homeheader></pm-homeheader>
<div layout="row">
<md-content ui-view flex></md-content>
</div>
</div>
</div>
Login blockcodes :
'use strict'
export default ['$rootScope', '$state', '$http', '$window', function($rootScope, $state, $http, $window) {
this.user = {};
this.login = () => {
$http.post('./api/auth/login', this.user)
.success(function(data, status, headers, config) {
$window.sessionStorage.token = data.token;
$rootScope.user = data.user;
$rootScope.isAuthenticated = true;
$state.go('home');
})
.error(function(data, status, headers, config) {
delete $window.sessionStorage.token;
})
};
}]
My problem is when I logged and go back to home state, the ui-router updated the template to ui-view, but the ng-show="$rootScope.isAuthenticated" didn't reflect the changes on html, it show the block codes of home page instead of dashboard page.
Can anyone help me for this case, many thanks.

Use:
ng-show="$root.isAuthenticated"
You can't access $rootScope in the template, when you access it in a controller you inject it in. $root works because when angular creates a rootScope it sets a reference to $root to itself so its just like accessing any other property on the scope.
Refer to AngularJS rootScope code Line 135: https://github.com/angular/angular.js/blob/v1.3.6/src/ng/rootScope.js#L135

You should not use either $scope OR $rootScope while using variable for binding on HTML, so as soon as variable update in $rootScope, isAuthenticated will be taken from $rootScope while evaluating value of ng-show.
ng-show="isAuthenticated"
Though directly using $rootScope, wouldn't consider as a good practice. I'd suggest you to create a service/factory with a name userService that will have shareable user information among-st angular components.

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>

Angular: Why Won't Model Update Outside Of View In Same Controller?

I have found a number of posts talking about models/views not updating, but I still can't figure this out. I'm new to Angular, btw so I suspect this is noob issue.
I have the below Angular app.
When the text input test_var is edited, the edited value isn't updated in the sidebar, but it is in the view. Why and how do I fix it?
This works when I don't use views and routes.
I've tried a sidebar controller, but no difference. I've tried $rootScope, which partially worked (it broke other functionality), but I'd prefer not to use a global scope.
Thanks for taking a look.
HTML
<body>
<div ng-app="rxApp" ng-controller="WizardCtrl">
<div class="ng-view">
</div>
<div class="sidebar">
<span ng-bind="test_var"></span>
</div>
</div>
</body>
View (One.html)
<input ng-model="test_var" />
<span ng-bind="test_var"></span>
Controller
rxApp.controller( 'WizardCtrl', function ( $scope, $http, $routeParams, $location, FileUploader ) {
$scope.test_var = 'please work!';
)};
Routes
rxApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/one', {
templateUrl: 'templates/one.html',
controller: 'WizardCtrl'
}).
when('/two', {
templateUrl: 'templates/two.html',
controller: 'WizardCtrl'
}).
otherwise({
redirectTo: '/one'
});
}
]);
Controllers are disposed when transmuting routes.
As for Best Practice you should create a Service to handle that data. You should not use controllers to carry data between views. In your case, the problem is Controllers are disposed when transmuting routes.
See the angular docs on how to use controllers correctly. http://docs.angularjs.org/guide/dev_guide.mvc.understanding_controller
The problem is the making of model variables.
You have to have a dot in model. Make your model point to an object.
So in your controller do like this -
rxApp.controller('WizardCtrl',function($scope, $http, $routeParams,$location, FileUploader){
$scope.test ={
var : 'please work!'
};
)};
View (One.html)
<input ng-model="test.var" />
<span ng-bind="test.var"></span>
HTML
<body>
<div ng-app="rxApp" ng-controller="WizardCtrl">
<div class="ng-view">
</div>
<div class="sidebar">
<span ng-bind="test.var"></span>
</div>
</div>
</body>
To read more about scope go through this UnderStanding Scopes

Want to associate a controller to main page in Angular

I am currently creating an app that has a nav bar. I want a particular function to be invoked every time the submit button in the nav bar is pressed regardless of route/view. I am having trouble because here in my routes file I have created associations that changed based on route. The form is found in <form class="pure-form" ng-submit="somefunc()">
routes.js
angular.module('LiveAPP', ['ngRoute',
'LiveAPP.main',
'LiveAPP.signUp',
'LiveAPP.artist'])
.config(function($routeProvider, $httpProvider) {
$routeProvider
.when('/', {
templateUrl : '/home.html',
controller : 'mainCtrl'
})
.when('/signup',{
templateUrl : '/signup.html',
controller : 'signUpCtrl'
})
.when('/artist',{
templateUrl : '/artistpage.html',
controller : 'artistCtrl'
})
})
index.html
<body ng-app='LiveAPP'>
<div class="header">
<form class="pure-form" ng-submit="somefunc(field)">
<input ng-model="field" type="text" placeholder="Artist" name="field">
<button type="submit">Search</button>
</form>
Sign Up
artistPage
</div>
<div ng-view></div>
</body>
mainCtrl
angular.module('LiveAPP.main',[])
.controller('mainCtrl', ['$scope','$http', '$location',mainCtrl]);
function mainCtrl($scope,$http,$location){
$scope.somefunc = function(searchvalue){
console.log(searchvalue)
}
};
Right now the submit button is associated with the mainCtrl which is related to the home.html. Any ideas?
In general you have a couple approaches:
If you need some logic to be available in more than one controller you can create a service and inject it to your controllers.
You can implement controller inheritance.
There are a couple ways to implement controller inheritance.
This is one example of how to do that:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function() {
this.methodclick=function(){
alert('I am Parents')
}
});
app.controller('ChildCtrl', function($controller) {
var ChildCtrl=this;
ChildCtrl.child = $controller('MainCtrl',{});
});
But in my opinion it is better to implement a service.

how to call parent method with dependencies in 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.

how do I change background image of application based on url or routing?

I would like to change the background image of the application(Html Body) based on the url. And this I want to do in angularJS only :)
For eg:
1) if user visits the url like this,
www.domain.com/view1
Bellow image is shown
2) If user visits url
www.domain.com/view2
I want show other image
app.js
var app = angular.module('app', []);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {templateUrl: 'partials/partial1.html', controller: 'MyCtrl1'});
$routeProvider.when('/view2', {templateUrl: 'partials/partial2.html', controller: 'MyCtrl2'});
$routeProvider.otherwise({redirectTo: '/view1'});
}])
app.config(['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode(true);
}]);;
Controler.js
app.controller('MyCtrl1',function($scope){
$scope.viewBackground="body"
console.log($scope.viewBackground);
})
app.controller('MyCtrl2',function($scope){
$scope.viewBackground="profile"
})
in the partial html, I am just doing like this
<div class="span12">
<p>
{{$scope.viewBackground}}zxz
</p>
</div>
But some reason I am not able to get the value of viewBackground property value.
I'm not sure I understand you correctly, but I hope so.
You have 2 options.
First - use different controllers for each page view1 and view2.
And use ng-class directive on the pages:
HTML:
<!-- "page" View 1 -->
<div ng-controller="View1Ctrl">
<div ng-class="viewBackground"> View 1 </div>
</div>
<!-- "page" View 2 -->
<div ng-controller="View2Ctrl">
<div ng-class="viewBackground"> View 2 </div>
</div>
JS:
var app = angular.module('app', []);
function View1Ctrl($scope) {
$scope.viewBackground = "background-small"
}
function View2Ctrl($scope) {
$scope.viewBackground = "background-big"
}
On your CSS:
.background-small{
height:200px;
width:200px;
background: url('...img1...');
}
.background-big{
height:400px;
width:400px;
background: url('...img2...');
}
Second option - use .run block, where you will add some logic to change the bg-image, but this is a poor option
If your controller you can check the $routeParams param and then set a scope variable to control the background image.
function announcements_detail_controller($scope, $rootScope, $routeParams, $http, $location)
{ //console.log($routeParams);
$scope.css_class_for_background_image = 'xxxx';//
}

Resources