My landing page component's controller doesn't retrieve any data when the app initially loads or when I reload from the landing page. I keep getting undefined for my variables when I have verified there is data.
If I click on the #/index link, the data loads fine and my variable logs to the console. Any idea why this happens to only the initial load of the webpage and when I reload it on the landing?
Edit: Added the appUser value that I am trying to log along with the app's main controller. Essentially, I run a service via appStore to retrieve user details. I then set my appUser value. I have confirmed the appStore service works.
It seems like the MainLandingCtrl runs before the AppCtrl
app.module.js:
angular.module('dup', ['ngRoute', 'mainLanding', 'unauthorized']);
app.value.js
angular.module('dup')
.value('appUser', {
fup: undefined
});
app.controller.js
angular.module('dup')
.controller('AppCtrl', ['appStore', 'appUser', '$log', function(appStore, appUser, $log) {
var rcAppTemp = this;
// User authorization
appStore.authorizedUser()
.then(function(response) {
rcAppTemp.userDetails = response.data;
appUser.fup = rcAppTemp.userDetails.fup;
}, function(error) {
$log.log('error');
});
}]);
app.config.js:
angular.module('dup')
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
// Main page
.when('/', {
template: '<main-landing></main-landing>'
})
.when('/unauthorized', {
template: '<unauthorized></unauthorized>'
})
.otherwise({
redirectTo: '/'
});
}]);
main-landing.controller.js:
angular.module('mainLanding')
.controller('MainLandingCtrl', ['appUser', '$log', function(appUser, $log) {
var mn = this;
mn.fup = appUser.fup;
$log.log(mn.fup);
}]);
main-landing.component.js
angular.module('mainLanding')
.component('mainLanding', {
bindings: {
},
templateUrl: 'components/main-landing/main-landing.template.html',
controller: 'MainLandingCtrl'
});
index.html:
<body ng-app="dup">
<div ng-controller="AppCtrl as app">
<!-- navigation bar (excluded for brevity) -->
</div>
<div ng-view></div>
</body>
main-landing.template.html
<div class="row">
<div class="small-12 medium-4 medium-offset-4 large-4 large-offset-4 columns">
<div title="Home">
<h5>Dup</h5>
<ul>
<li><strong>Index</strong></li>
<li ng-show="$ctrl.fup><strong>Trouble</strong></li>
</ul>
</div>
</div>
</div>
Related
I have been working on Single Page Application in Angularjs. When index page loads I have loaded other pages into index page by using Angular ng-include.
Now it's working, But in the URL it's showing like http://localhost:8080/Index.html#/Home.html, I want to remove "#". I applied , after applying the base tag in the head tag "ng-include" not working. I tried other online stuff but I couldn't find any solution. I am using xampp server.
Thanks in Advance friends
<body ng-app="mainApp" ng-controller="mainCtrl">
<header ng-include="'navigation.html'" ng-controller="headerCtrl">
</header>
<div class="container">
<h3>{{Title}}</h3>
<div ng-include="'leftNavigation.html'" ng-controller="leftDivCtrl">
</div>
<div ng-include="'rightPage.html'" ng-controller="rightDivCtrl">
</div>
<div class="clearfix"></div>
<ng-view></ng-view>
</div>
</body>
var app = angular.module("mainApp", ["ngRoute"])
// Navigating external pages
.config(function($routeProvider, $locationProvider){
$routeProvider
// $routeProvider .when( '/', { redirectTo: '/home' })
.when("/Home", {
templateUrl: "partials/Home.html",
controller:"homeCtrl",
})
.when("/Aboutus", {
templateUrl: "partials/Aboutus.html",
controller:"AboutusCtrl",
})
.when("/Courses", {
templateUrl: "partials/Courses.html",
controller:"CoursesCtrl",
})
.when("/Contactus", {
templateUrl: "partials/Contactus.html",
controller:"ContactusCtrl",
})
.otherwise({
redirectTo:"Index.html"
})
//$locationProvider.hashPrefix('')
$locationProvider.html5Mode({
enabled:true,
//requireBase:false
})
})
.controller("homeCtrl", function($scope){
$scope.msg = "Home Page";
})
.controller("AboutusCtrl", function($scope){
$scope.msg = "Aboutus Page";
})
.controller("CoursesCtrl", function($scope){
$scope.msg = "Courses Page";
})
.controller("ContactusCtrl", function($scope){
$scope.msg = "Contactus Page";
})
app.controller("mainCtrl", ["$scope", function($scope){
$scope.Title = "Single Page Application";
}]);
// loading external pages as includes, when index page loads
app.controller("headerCtrl", ["$scope", function($scope){
}]);
app.controller("leftDivCtrl", ["$scope", function($scope){
}]);
app.controller("rightDivCtrl", ["$scope", function($scope){
}]);
Sounds like you need to define the $locationProvider to use html5 mode.
So in your config phase just add this line:
$locationProvider.html5Mode(true);
I am using ui-router for my routing, and am going to be using nested scopes and therefore want to be using the 'controller as' syntax. However, I can't work out the correct syntax / combinations to access the controller object properties in my view.
app.js (sets up routing)
(function() {
angular
.module('ICP_App', ['ui.router', 'satellizer', 'ngMaterial', 'ngMessages', 'xeditable'])
.config(function($stateProvider, $urlRouterProvider, $authProvider) {
$urlRouterProvider.otherwise('dashboard');
$stateProvider
.state('clients', {
url: '/clients',
templateUrl: '../partials/clients-index.html',
controller: 'ClientsController as ClientsCtrl'
})
// more routes here...
})();
ClientsController.js
(function() {
angular.module('ICP_App')
.controller('ClientsController', function($http) {
$http.get('http://api.icp.sic.com/clients')
.success(function(clients) {
var vm = this;
vm.clients = clients.data;
console.log(vm.clients);
})
.error(function(error) {
// handle here
})
});
})();
index.html
<body ng-app="ICP_App" ng-cloak>
<!-- sidebar, header etc -->
<div ui-view></div> <!-- pull in view -->
</body>
Finally, clients-index.html partial
<div class="content">
<div class="pane" ng-repeat="client in clients">
{{ client.name }}
</div>
</div>
I have also tried client in vm.clients, to no avail.
Is there a problem with my controller as syntax? As I am using controller as in my ui-router code, yet not again when creating my controller. If I use controller as again in my controller, it errors (Argument ClientsController is not a).
I should point out that console logging vm.clients does give me the data in the console, I just can't seem to access it in my view.
Thanks in advance.
Modify your ClientsController as follow
(function() {
angular.module('ICP_App')
.controller('ClientsController', function($http) {
var vm=this;
$http.get('http://api.icp.sic.com/clients')
.success(function(clients) {
vm.clients = clients.data;
console.log(vm.clients);
})
.error(function(error) {
// handle here
})
}); })();
Modify client-index.html as following
<div class="content">
<div class="pane" ng-repeat="client in ClientsCtrl.clients">
{{ client.name }}
</div>
Below link will help you to understand controller as syntax more deeply
https://toddmotto.com/digging-into-angulars-controller-as-syntax/
I am using UI-Router for an Angular app. I can't seem to find what I am doing wrong. I am also not getting any errors which is making it really difficult for me to debug. Followed the docs as well and I am following their steps. My controller function is working when I don't nest it in a child view. Can someone please direct me to what I am doing wrong? Thanks in advance!
APP.JS
'use strict';
var app = angular.module('americasTopStatesApp', ['ui.router', 'ngAutocomplete']);
app.run(function($state, $rootScope) {
$rootScope.$state = $state;
});
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider
.otherwise('/home');
$stateProvider
//HOME
.state('home', {
url: '/home',
templateUrl: './app/views/homeTmpl.html',
controller: 'homeCtrl'
})
//RANKINGS
.state("rankings", {
url: "/rankings",
templateUrl: './app/views/rankingsTmpl.html',
controller: 'rankingsCtrl'
})
// RANKINGS CHILDREN
.state('rankings.data', {
url: '/data',
templateUrl: './app/views/rankingsDataTmpl.html',
controller: 'rankingsCtrl',
parent: 'rankings'
})
});
CONTROLLER rankingsCtrl
'use strict';
app.controller('rankingsCtrl', function($scope, rankingsService) { //Start Controller
// ***********************************************
// *************** GET LATEST DATA ***************
// ***********************************************
$scope.getAllStateRankings = function() {
rankingsService.getStateRankingsData().then(function(data) {
$scope.showRankings = true;
// console.log("Contoller Data", data);
$scope.states = data;
});
};
$scope.showRankings = false;
$scope.getAllStateRankings();
}); //End Controller
PARENT VIEW rankingsTmpl.html
<div class="rankings-heading">
<h1>America's Top States</h1>
<button ng-click="getAllStateRankings()">
<a ui-sref="rankings.data" id="data" class="btn">Data</a>
</button>
</div>
</div ui-view></div>
Child View (Nested ui-view) rankingsDataTmpl.html
<div class="rankings-container" ng-show="showRankings">
<div class="panel panel-primary" ng-repeat='state in states'>
<div class="panel-heading">
<h3 class="panel-title">{{state.state}}</h3>
</div>
<div class="panel-body">
Economy: {{state.economy}}<br>
Capital Access: {{state.accessToCapital}}<br>
Business: {{state.business}}<br>
Cost of living: {{state.costOfLiving}}<br>
</div>
</div>
</div>
Screen Shot
There is a working plunker
In this case, when we have parent child and angular's UI-Router, we should not use solution based on
parent and child has same controller. // WRONG approach
Because they in fact do have JUST same type. The instance of that type 'rankingsCtrl' in runtime is different.
What we need is:
How do I share $scope data between states in angularjs ui-router?
scope inheritance, driven by reference object, e.g. $scope.Model = {}
There is adjusted controller:
.controller('rankingsCtrl', ['$scope', function($scope) {
$scope.Model = {};
$scope.getAllStateRankings = function() {
//rankingsService.getStateRankingsData().then(function(data) {
$scope.Model.showRankings = true;
// console.log("Contoller Data", data);
$scope.Model.states = data;
//});
};
$scope.Model.showRankings = false;
$scope.getAllStateRankings();
}])
At the end, child can have different controller with its own logic for the child view:
.state("rankings", {
url: "/rankings",
templateUrl: 'app/views/rankingsTmpl.html',
controller: 'rankingsCtrl'
})
// RANKINGS CHILDREN
.state('rankings.data', {
url: '/data',
templateUrl: 'app/views/rankingsDataTmpl.html',
controller: 'rankingsChildCtrl',
parent: 'rankings'
})
Also, the parent view should have fixed div:
// wrong
</div ui-view></div>
// starting tag
<div ui-view></div>
Check it here in action
I'm going to try my best to explain this problem. I am also new to Angular so bear with me.
I have two routes that use the same template...
ExampleApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/logbook/following', {
templateUrl: 'views/surf.html',
})
.when('/logbook/following/:surf_id', {
templateUrl: 'views/surf.html',
})
}]);
with two controllers
AppControllers.controller('LogbookController', function($scope, $http, $location, $routeParams) {
$scope.surfs = null;
// Get feed
$http.get(RestURL + 'feeds?filter=following' ).success(function(data) {
if(typeof $routeParams.surf_id == "undefined") {
if(data.length > 0) {
$location.path('/logbook/following/' + data[0].id);
$scope.loadSurfDetail(data[0].id);
}
}
$scope.surfs = data;
});
});
AppControllers.controller('SurfController', function($scope, $http, $location, $routeParams) {
$scope.loading = false;
// Load surf
$scope.loadSurfDetail = function(surfID) {
$scope.loading = true;
$scope.selectedSurf = null;
// Get surf
$http.get(RestURL + 'surfs/' + surfID).success(function(data) {
$scope.selectedSurf = data;
$scope.loading = false;
});
};
if($routeParams.surf_id) {
$scope.loadSurfDetail($routeParams.surf_id);
}
});
using this template file:
<div class="row">
<div class="logbook col-md-3" ng-controller="LogbookController">
<h1>Logbook</h1>
<ol class="surfs-feed">
<li data-id="{{feedSurf.id}}" ng-repeat="feedSurf in surfs" class="surf">
<a href="#/logbook/following/{{feedSurf.id}}">
<strong>{{feedSurf.user.first_name}} {{feedSurf.user.last_name}}</strong>
</a>
</li>
</ol>
</div>
<div class="surf col-md-9" ng-controller="SurfController">
<p class="alert alert-info" ng-show="loading">
Loading...
</p>
<div class="surf-detail" ng-show="selectedSurf">
<pre>
{{selectedSurf | json}}
</pre>
</div>
</div>
</div>
My issue is that when I load a deep link URL, ie. /logbook/following/:surf_id it will use the same template as /logbook/following (adove) and that will cause the logbook feed to be regenerated each time you load up a new surf. So each time you load the surf, the logbook "blinks" and regenerates.
I would like to know how people have tackled this problem without refreshing the feed of surfs and just updating the detail panel on the right hand side...
Thanks!
In your app config, inject $locationProvider and set its html5Mode parameter to true. Then, route changes will not cause the page to refresh.
ExampleApp.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
.when('/logbook/following', {
templateUrl: 'views/surf.html',
})
.when('/logbook/following/:surf_id', {
templateUrl: 'views/surf.html',
})
$locationProvider.html5Mode(true);
}]);
I have the following configuration:
$routeProvider
.when('/cars', { templateUrl: 'app/cars/index.html', controller: 'CarsCtrl', reloadOnSearch: false })
.when('/bikes', { templateUrl: 'app/bikes/index.html', controller: 'BikesCtrl', reloadOnSearch: false });
and somewhere in my root index.html there is a:
Cars
Bikes
<div ng-view></div>
Now, I want both views loaded and generated in the DOM at the same time, and show one of them depending on the route/URL.
Something like the following (not actual working code, just to give you an idea).
app.js:
$routeProvider
.when('/cars', { controller: 'CarsCtrl', reloadOnSearch: false })
.when('/bikes', { controller: 'BikesCtrl', reloadOnSearch: false });
root index.html:
Cars
Bikes
<div ng-include="'app/cars/index.html'" ng-show="carsVisible"></div>
<div ng-include="'app/bikes/index.html'" ng-show="bikesVisible"></div>
UPDATE: I know that ng-view kind of does this, but the difference, if subtle, exists. I want the html of each view to be generated once and stay in the DOM at all times.
I created a single RouteCtrl to load all of your views via ng-include. ng-view is not used. I inlined the templates. The templates could contain their own ng-controller directives to pull in specific controllers.
<body ng-controller="RouteCtrl">
Cars
Bikes
<div ng-controller="RouteCtrl">
<div ng-include="'/cars.html'" ng-show="carsVisible"></div>
<div ng-include="'/bikes.html'" ng-show="bikesVisible"></div>
</div>
<script type="text/ng-template" id="/cars.html">
Cars template.
</script>
<script type="text/ng-template" id="/bikes.html">
Bikes template.
</script>
$routeProvider is still configured, but no template or controller is specified, causing the RouteCtrl to always be active. That controller listens for the $routeChangeSuccess event and manipulates the ng-show properties accordingly.
app.config(function($routeProvider) {
$routeProvider
.when('/cars', {} )
.when('/bikes', {})
});
app.controller('RouteCtrl', function($scope, $route, $location) {
$scope.$on('$routeChangeSuccess', function() {
var path = $location.path();
console.log(path);
$scope.carsVisible = false;
$scope.bikesVisible = false;
if(path === '/cars') {
$scope.carsVisible = true;
} else if(path === '/bikes') {
$scope.bikesVisible = true;
}
});
});
Plunker
The idea for this solution is from #Andy.
I found another way, which I think is the simplest, quickest and most manageable:
How to set bootstrap navbar active class with Angular JS?
Which is:
Use ng-controller to run a single controller outside of the ng-view:
<div class="collapse navbar-collapse" ng-controller="HeaderController">
<ul class="nav navbar-nav">
<li ng-class="{ active: isActive('/')}">Home</li>
<li ng-class="{ active: isActive('/dogs')}">Dogs</li>
<li ng-class="{ active: isActive('/cats')}">Cats</li>
</ul>
</div>
<div ng-view></div>
and include in controllers.js:
function HeaderController($scope, $location)
{
$scope.isActive = function (viewLocation) {
return viewLocation === $location.path();
};
}
Instead of using ng-include, you should use ng-view;
This will display the content of either app/cars/index.html or app/bikes/index.html
Cars
Bikes
<div ng-view></div>
See the Template section from http://docs.angularjs.org/tutorial/step_07
Use a service with a show directive:
<div ng-show="myService.isActive('/')">Show this when at default route</div>
<div ng-show="myService.isActive('/cars')">Show this when at cars</div>
Service:
myApp.factory('MyService',
function ($location) {
return {
isActive: function (path) {
return (($location.path() == path));
}
}
}
);
App.js:
// this is run after angular is instantiated and bootstrapped
myApp.run(function ($rootScope, myService) {
$rootScope.breadcrumbService = MyService;
});