Invoke parent controller while loading child controller - angularjs

I have the parent view defined as:
<div ng-app="myProSupMod" ng-controller="DefaultController" class="container">
<div class="row">
<div class="col-md-12">
<div class="page-header">
<img src="~/Content/Images/logo.jpg" />
<b class="projectTitle">Production Support Tool</b>
</div>
</div>
<div ng-show="DefaultProps.UserDivVisible" class="page-header"
style="font-weight:bold;height:30px;border-bottom:1px solid #d1d1d4;width:100%">
<div style="float:right;"><span style="margin-right:10px;">
Welcome
<a class="text-success" href="#">
{{DefaultProps.LoggedInUsername }}
</a></span>|
<a href="#" style="margin-left:5px;" class="text-danger"
ng-click="LogUserOut()">Logout
</a>
</div>
</div>
</div>
<ng-view></ng-view>
</div>
Its controller:
myProSupMod.controller("DefaultController", ['$scope', '$rootScope',
'$location', '$route', function ($scope, $rootScope, $location, $route) {
if (!sessionStorage.getItem("LoggedInUsername")) {
$scope.DefaultProps = {
LoggedInUsername: "",
UserDivVisible: false
};
$location.path('/');
}
else {
$scope.DefaultProps = {
LoggedInUsername: sessionStorage.getItem("LoggedInUsername"),
UserDivVisible: true
};
}
$scope.LogUserOut = function () {
sessionStorage.setItem("UserDivVisible", false)
$location.path('/')
}
}])
And one of my child child controller is like
myProSupMod.controller("LoginController", ['$scope', '$rootScope',
'$uibModal', 'LoginService', '$location', function ($scope, $rootScope,
$uibModal, LoginService, $location) {
$scope.DefaultProps.LoggedInUsername = ""
$scope.DefaultProps.UserDivVisible = false
$scope.Login = {
Username: '',
Password: '',
Error: '',
validateLogin: function () {
$scope.Login.Error = ''
$scope.DefaultProps.LoggedInUsername =
sessionStorage.getItem("LoggedInUsername")
$scope.DefaultProps.UserDivVisible =
sessionStorage.getItem("UserDivVisible")
$scope.Login.Username = $scope.Login.Password = ''
$location.path('/Home')
}
}
}])
The statements
$scope.DefaultProps.LoggedInUsername=sessionStorage.getItem("LoggedInUsername")
and
$scope.DefaultProps.UserDivVisible =sessionStorage.getItem("UserDivVisible")
are really changing the values of the properties in the "Default" controller but routing to an other view both the "Default" controller properties "LoggedInUsername" and "UserDivVisible" are gone.It looks like i may need to have both the above statements in every other view i'm going to navigate to.
Is there an other way?
"Default" view being the parent, the controller is invoked only once at the start of the application upon navigating to other view the "Default" controller is never invoked.
But if i reload any page by clicking "reload" on the browser or hitting "enter" on the URL i see the "Default" controller being invoked, which is what i want to happen when i'm also navigating to other view via angular routing.

For clarity, here is a simplified template:
<div ng-app="myProSupMod" ng-controller="DefaultController">
<div ng-show="DefaultProps.LoggedInUsername">
Welcome {{DefaultProps.LoggedInUsername}}
<button ng-click="LogUserOut()">Logout<button>
</div>
<ng-view></ng-view>
</div>
Make the controller lightweight:
app.controller("DefaultController", function($scope, LoginService) {
$scope.DefaultProps = LoginService.getProps();
$scope.LogUserOut = function () {
LoginService.logout();
};
})
With the functions inside a service, they can be called by any controller and they are encapsulated in a way that makes the code easier to understand, debug, and maintain.

Related

Apply jquery after rendering angularJS HTML

i have rendering HTML after AngularJS call
Its controller is
App.controller('controller', ['$scope', '$http', '$sce', '$routeParams', '$location', function ($scope, $http, $sce, $routeParams, $location) {
$http({
//http call
}).then(function (response) {
$scope.requestpurpose = $sce.trustAsHtml(response.data.requestpurpose);
$scope.$watch('requestpurpose', function(newValue, oldValue) {
if(typeof newValue != 'undefined'){
alert(newValue);
showAlreadySelected();
}
});
}]);
and its jquery script is
<script type="text/javascript">
// it will show the div depending on purpose of request
function showAlreadySelected(){
if ($("#1").is(":checked")) {
$("#veterinarian-info").show();
} else {
$("#veterinarian-info").hide();
}
}
</script>
This is my HTML
<div class="row purpose-box" >
<div class="col-sm-12" ng-bind-html="requestpurpose"></div>
</div>
and after ajax call below html is renering in ng-bind-html
<div class="boxes-check">
<div class="box-one">
<input checked="checked" rev="Annual exam" type = "checkbox" name = "request_purpose[]" ng-model=formData.request_purpose[1] onChange="angular.element(this).scope().changePurpose(this)" value = "1" class = "md-check" id = "1" >
</div>
<div class="box-two">
<label title="" for="1">
<span></span>
<span class="check"></span>
<span class="box"></span> Annual exam
</label>
</div>
</div>
<div class="boxes-check">
<div class="box-one">
<input checked="checked" rev="Spay or neuter surgery" type = "checkbox" name = "request_purpose[]" ng-model=formData.request_purpose[2] onChange="angular.element(this).scope().changePurpose(this)" value = "2" class = "md-check" id = "2" >
</div>
<div class="box-two">
<label title="" for="2">
<span></span>
<span class="check"></span>
<span class="box"></span> Spay or neuter surgery
</label>
</div>
</div>
but i am facing problem is after angular load its calling showAlreadySelected function but does not selected "#1" and one thing if any body can help is any Jquery function which will hit whenever input element with id "#1", "#2" render into my ng-bind-html div.
First, I would move the watcher outside the then because you're registering a new watcher everytime you make the ajax call.
I tried, it works to have a number as ID (but not recommended though). We'll need your HTML code as well cause it should work the way you've implemented. Is the #1 node added by the ajax call ( = present in $scope.requestpurpose) or is it always present in the DOM ?
Also, can you add a console.log in the showAlreadySelected function to be sure it's called.
EDIT
App.controller('controller', ['$scope', '$http', '$sce', '$routeParams', '$location', function ($scope, $http, $sce, $routeParams, $location) {
$http({
//http call
}).then(function (response) {
$scope.requestpurpose = $sce.trustAsHtml(response.data.requestpurpose);
showAlreadySelected();
});
}]);
I have bind class with DOMSubtreeModified to detect changes within a div
$('.purpose-box').bind("DOMSubtreeModified",function(){
showAlreadySelected();
});

Angular ng-bind disappearing using escaped fragments with Mean-SEO

I have an angular web app that I am trying to get escaped_fragments to work using Mean-seo (under the covers it uses phantomjs headless browser)
I am getting strange behaviour I can't explain.
The non escaped fragment works fine.
With escaped fragments some of the content immediately disappears.
I have an object that I am reading from the mongo db in the resolve section of the routes config like so.
state('view-creator-test', {
url: '/view-creator-test/:creatorId',
templateUrl: 'modules/creators/views/view-creator-test.client.view.html',
resolve: {
creator: function($stateParams, Creators) {
return Creators.get({
creatorId: $stateParams.creatorId
}).$promise;
}
},
controller: function($scope, creator) {
$scope.resolveCreator = creator;
}
}).
then the view template is
<section data-ng-controller="CreatorTestController" >
<!-- !CREATOR PROFILE -->
<section class="profile-header inverse">
<div class="container">
<!-- AVATAR -->
<div class="row">
<!-- NAME / LOCATION -->
<div class="col-sm-8 col-sm-offset-1 col-xs-12 text-center-sm">
<div class="row">
<div class="col-sm-6 col-xs-12">
<h2 class="name">{{creator.name}}</h2>
<h2 class="name" ng-bind="creator.name"></h2>
</div>
<h2 class="name">{{test}}</h2>
<h2 class="name" ng-bind="test"></h2>
</div>
</div>
</div>
</div>
</section>
</section>
then the controller is
'use strict';
angular.module('creators').controller('CreatorTestController', ['$scope',
function($scope) {
$scope.test = 'Leo was Here';
$scope.creator = $scope.resolveCreator;
}]);
the result is that the creator name is filled in for {{creator.name}} but is not filled in for ng-bind="creator.name".
'Leo was here' is filled in for both.
Thanks
Instead of defining controller function in state and then do assign that $scope inside variable through template, you could place the CreatorTestController inside the route, so that you directly inject the dependency inside the CreatorTestController function, Remove ng-controller from the template
.state('view-creator-test', {
url: '/view-creator-test/:creatorId',
templateUrl: 'modules/creators/views/view-creator-test.client.view.html',
resolve: {
creator: function($stateParams, Creators) {
return Creators.get({
creatorId: $stateParams.creatorId
}).$promise;
}
},
controller: 'CreatorTestController'
})
Controller
'use strict';
angular.module('creators').controller('CreatorTestController', ['$scope', 'creator', //<-- injected resolve method here.
function($scope, creator) {
$scope.test = 'Leo was Here';
$scope.creator = creator;
}]);

updating value in $scope in a sub state not working angularjs

I have a parent state which shows the list of apartments, on clicking any apartment a sub state is loaded which shows all the images for it. But value of $scope is not passing to ng-repeat. What possible mistake i have made here.
app.js :
state('projects', {
url: '/projects',
templateUrl : 'resources/partials/projectsNew.html',
controller : 'ProjectsController'
}).state('projects.project', {
url: '/project/:param',
templateUrl : 'resources/partials/projectImages.html',
controller : 'ProjectController'
})
Controllers :
decorpotCtrls.controller('ProjectsController', [ '$scope', 'cart', 'projects', '$rootScope',
function($scope, cart, projects, $rootScope) {
projects.getAllProjects().success(function(data) {
for (var i = 0; i < data.length; i++) {
data[i].APARTMENT = data[i].APARTMENT.replace(/\s+/g, '-');
}
$scope.projects = data;
});
} ]);
decorpotCtrls.controller('ProjectController', [
'$scope',
'cart',
'projects',
'$stateParams',
'$rootScope',
function($scope, cart, projects, $stateParams, $rootScope) {
var project = $stateParams.param;
projects.getImagesByAppartment(project).success(function(data) {
$scope.images = data;
console.log($scope.images);
});
} ]);
html :
ProjectsNew.html :-
<div class="pastProjects" ui-view>
<div class="col-md-3 .col-xs-12 .col-sm-6 imgContainerOuter"
ng-repeat="project in projects | filter:query">
<div class="imgContainer">
<a class="shrink"ui-sref="projects.project({param : '{{project.APARTMENT}}'})">
<img src={{project.SMALL_PATH}}>
</a>
</div>
<div class="textProjects">
<h4>{{project.APARTMENT}}</h4>
<span>Bangalore</span>
</div>
</div>
projectImages.html :-
<div id="gallery">
<a href="{{image.HD_PATH}}" ng-repeat="image in images | filter:query">
<img src="{{image.SMALL_PATH}}" alt="Photo 1" /></a>
</div>
when i am navigating from parent state projects to project ng-repeat doesnt works. I put a console log in ProjectController for the value of images its being populated correctly.

AngularJS $scope.$parent strange hierarchy

I'm trying to access the $parent in my child controller but for some reason I have to access the Fifth $parent in order to get the actual $scope from the Parent controller, Any Ideas?
Parent Controller
angular.module('App')
.controller('HomeController', ['$scope', '$rootScope', 'user',
function($scope, $rootScope, user) {
$rootScope.currentNav = 'home';
$rootScope.currentUser = user.data;
$scope.tabs = [
{
heading : 'Empresas',
template : 'home_companies_tab.html'
},
{
heading : 'Tickets',
template : 'home_tickets_tab.html'
}
];
$scope.companies = []
$scope.selectedCompanyIndex = undefined;
$scope.selectedCompany = undefined;
$scope.selectedTicketIndex = undefined;
$scope.selectedTicket = undefined;
}]);
Child Controller
angular.module('App')
.controller('HomeCompaniesTabController', ['$scope', 'Companies',
function($scope, Companies) {
$scope.loadCompanies = function () {
$scope.companies = Companies.query();
}
/**
* Init
*/
$scope.selectCompany = function (company, index) {
$scope.$parent.selectedCompanyIndex = index; //this doesnt work
$scope.$parent.$parent.$parent.$parent.$parent.selectedCompany = company; //this does, why?
console.log($scope);
}
if($scope.currentUser.security < 3) {
$scope.loadCompanies();
}
}]);
Home template
<div ng-include="'dist/templates/header.html'"></div>
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
company : {{selectedCompany}}
</div>
</div>
<tabset>
<tab ng-repeat="tab in tabs" heading="{{tab.heading}}">
<div ng-include="'dist/templates/' + tab.template" ></div>
</tab>
</tabset>
</div>
Child template
<div class="row-fluid" ng-controller="HomeCompaniesTabController">
<div class="col-md-3">
<h4>Lista de Empresas</h4>
<hr/>
<div class="list-group">
<a
href=""
class="list-group-item"
ng-repeat="company in companies"
ng-click="selectCompany(company, $index)">
<h4 class="list-group-item-heading">
{{company.name}}
</h4>
</a>
</div>
</div>
<div class="col-xs-9">
<div ng-show="selectedCompany">
<h4><b>{{selectedCompany.name}}</b></h4>
</div>
</div>
Based on the comments of charlietfl I came up with this simple service for sharing data
angular.module('App')
.factory('SharedData', [function () {
return {
}
}]);
Then I simply inject it in the controllers
angular.module('App')
.controller('HomeController', ['$scope', '$rootScope', 'user', 'SharedData',
function($scope, $rootScope, user, SharedData) {
$rootScope.currentNav = 'home';
$rootScope.currentUser = user.data;
$scope.sharedData = SharedData;
$scope.tabs = [
{
heading : 'Empresas',
template : 'home_companies_tab.html'
},
{
heading : 'Tickets',
template : 'home_tickets_tab.html'
}
];
$scope.companies = [];
}]);

AngularJS scope does not change twice controller

I tried to change value on my DOM. but it doesn't work well.
This is my source
<div class="header_player_info" ng-controller="playerCtrl">
<div>{{ playbackTimeCurrent }} / {{ playbackTimeTotal }}</div>
{{playerInfo.song}}
</div>
<div class="ut_player" ng-controller="playerCtrl">
<div>
<span>{{ playbackTimeCurrent }} / {{ playbackTimeTotal }}</span>
<div> {{playerInfo.song}}</div>
<div>{{playerInfo.artist}}</div>
</div>
</div>
When called $scope.updatePlayerInfo PlayerCtrl's $scope will be change,
but only second DOM ng-controller="playerCtrl" apply $scope data. First ng-controller="playerCtrl" does not bind scope data.
any problem with my logic?
app.controller('playerCtrl', ['$scope', '$http', '$location', 'playList', function ($scope, $http, $location, playList) {
$scope.playerInfo = { // init playerInfo
cover: 0,
song: "Please select song."
}
//Other $scope Function call updatePlayerInfo.
$scope.updatePlayerInfo = function(songData) {
$scope.playerInfo = {
cover: songData.cover,
key: songData.key,
song : songData.song_en,
artist: songData.artist_en
};
$scope.playerPaused = false;
};
}]);

Resources