Simple way to display $state data using ui-router - angularjs

I've seen all the other answers for similar questions but I think this is different.
I have a state defined as such:
.state('2col.flight-log', {
url: 'flight-log',
templateUrl: 'components/2col-pages/flight-log/flight-log.html',
data : { pageTitle: 'Flight Log' }
})
Within flight-log.html I'd like to do something like {{$state.current.data.pageTitle}} or {{$state.data.pageTitle}}. However, this doesn't work. Am I doing something wrong?
I understand the state change issue inherent with this approach but this is fine for now. If I have to create a directive I will, but it really seems like overkill. Should the way I've outlined work?

Here's how I got it working:
app.run([ '$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}])
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
app.state('2col.flight-log', {
url: 'flight-log',
templateUrl: 'components/2col-pages/flight-log/flight-log.html',
data : { pageTitle: 'Flight Log' }
})
and in flight-log.html I put {{$state.current.data.pageTitle}} wherever I needed it.
What's important about this is the app.run block. From the documentation "A run block is the code which needs to run to kickstart the application. It is executed after all of the service have been configured and the injector has been created."

This is how I do it:
Set at $rootScope a ref to $state in app.run
var app = angular.module('app', ['ui.router']);
app.run(['$rootScope', '$state', '$stateParams',
function($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
]);
app.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$urlRouterProvider
.otherwise('/');
$stateProvider
.state("home", {
url: "/",
template: 'HELLO WORLD',
data: {
myData: "Working!"
}
});
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
<script src="https://cdn.jsdelivr.net/angular.ui-router/0.2.10/angular-ui-router.js"></script>
<pre ng-app="app" id="uiRouterInfo">
$state = {{$state.current.name}}
$stateParams = {{$stateParams}}
$state full url = {{ $state.$current.url.source }}
$state my data = {{ $state.$current.data.myData }}
</pre>

Related

Pass parameter from Angularjs controller to $stateProvider

This is my Angularjs .config file that opens lead.html page whenever 'tasks' is activated from another html using ui-router.
App
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider){
$stateProvider
.state('tasks', {
templateUrl: {{name}}.html,
controller:"TasksController"
});
}]);
This is my Taskscontroller.js
App
.controller(
"TasksController", [function($scope, $http,$window) {
var self = this;
self.name = 'lead'; // I wanna use this parameter in templateUrl
console.log("In tasks Controller");
}]);
I want to make the templateUrl take parameter from TasksController so that it redirects to relevant page based on the parameter set in TasksController.
Please guide me how to do this.
Thanks
You could try using $stateParams:
App.config(['$stateProvider', '$urlRouterProvider', '$stateParams', function($stateProvider, $urlRouterProvider, $stateParams) {
$stateProvider
.state('tasks', {
params: {
page: null
},
templateUrl: {{$stateParams.page}}.html,
controller: "TasksController"
});
}]);
Then in your controller:
App.controller("TasksController", [function($scope, $http, $window, $stateParams, $state) {
var self = this;
self.$stateParams.page = 'some_url.html';
self.$state.go('tasks');
}]);
Don't forget the injection in the controller too. Haven't tested this but you may need the $state go like this:
self.$state.go('tasks', { page: 'some_url.html' }, { });

$stateParams is empty object

i saw a lot of similar questions at SO, but those solutions not worked for me :(
About my site and app:
backend is wordpress with json api, angular app is on the mysite.lc/catalog/ page.
my controller:
var catalogControllers = angular.module('catalogControllers', []);
catalogControllers.controller('catalogCtrl', ['$scope', '$state', '$stateParams',
function ($scope, $state, $stateParams) {
$log.debug(angular.toJson($stateParams, true));
$http.get(url).success(function(data) {
console.log('data is loaded');
});
}
]);
my routing setup:
var catalogApp = angular.module('catalogApp', ['ui.router', 'ngResource', 'ngSanitize', 'catalogControllers']);
catalogApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '?producttype&colors&models',
controller: 'catalogCtrl',
onEnter: function() {
console.log('route entered');
}
});
$urlRouterProvider.otherwise("/");
}]);
So when i go to url like http://mysite.lc/catalog/#/?producttype=4&colors=5,7,9&models=17 console shows
{} from catalogCtrl, then
data is loaded from catalogCtrl $http.get, and only after that
route entered
If i do log it that way (at router config) controller: function($stateParams) { console.log($stateParams); } it doesn't output anything.
I would suggest resolving the $stateParams on its corresponding state on the .config section. Also,if it is your intention, you need to make your url name part of the url property and not just the stateParameters because ui-router doesn't automatically assign 'home' just because you declared it to be the home state. You can also make the parameters optional by declaring the 'params' property and setting everything to null.
var catalogApp = angular.module('catalogApp', ['ui.router','ngResource', 'ngSanitize', 'catalogControllers']);
catalogApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
params: {
productType: null,
colors: null,
models: null
}
url: '/home?productType&colors&models',
controller: 'catalogCtrl',
resolve: {
parameters: function($stateParams){
return $stateParams;
}
}
});
$urlRouterProvider.otherwise("/");
}]);
and to view it in the console, I would suggest using $log to preserve the sequence of it (I had this problem before using console.log) and angular.toJson to display the data;
var catalogControllers = angular.module('catalogControllers', []);
catalogControllers.controller('catalogCtrl', ['$scope', 'parameters', '$log'
function ($scope, parameters, $log) {
$log.debug(angular.toJson(parameters, true));
//the 'true' arguments makes the json 'prettyfied'
}
]);
let me know how it goes because it's a bit unorthodox for me to create the app which doesn't start from the root page.
I've found what was the problem, and it's small and easy (as usually :) ).
Actually everything worked fine, but i had some unmentioned $http.get calls in code above, and my logging was before any data has been loaded, so firstly i logged my $stateParams and only after that (after data has been loaded) my "home" state has been achieved.
So solution is to put work with $stateParams into $http.get(..).success() function.
So now my controller looks like
var catalogControllers = angular.module('catalogControllers', []);
catalogControllers.controller('catalogCtrl', ['$scope', '$state', '$stateParams',
function ($scope, $state, $stateParams) {
$http.get(url).success(function(data) {
console.log('data is loaded');
$log.debug(angular.toJson($stateParams, true));
});
}
]);
router:
var catalogApp = angular.module('catalogApp', ['ui.router', 'ngResource', 'ngSanitize', 'catalogControllers']);
catalogApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '?producttype&colors&models',
controller: 'catalogCtrl',
onEnter: function() {
console.log('route entered');
}
});
$urlRouterProvider.otherwise("/");
}]);
URL like http://mysite.lc/catalog/#/?producttype=4&colors=5,7,9&models=17 now outputs in console this:
data is loaded from $http.get in controller
route entered from router
{ "producttype": "4", "colors": "5,7,9", "models": "17" } from $stateParams in controller
Please add your comment, because i'm really newbie in angular and will appreciate any opinions on that.

Angular ui-router equivalent to reload $route?

I'm making the transition from NgRoute to ui-router using angular 1.0.8. Due to the fact I had some nested views I had to reload the routes which worked fine with ngRoute. I'm having the same issue with ui-router, is there an equivalent method I can use for this at all?
I'm using ui-router 0.2.10.
Edit:
I've created a fiddle to illustrate the issue that I'm having loading a basic view using ui-router.The view is requested and I can see it in the network inspector. The thing I can get my head around is why the view in not being injected into the template.
What am I missing here?
.run(function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
});
You are looking for the reload() function:
$state.reload()
http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state
You would put this in a controller like so:
var app angular.module('app', ['ui.router']);
app.controller('ctrl', function ($scope, $state) {
$scope.reload = function(){
$state.reload();
}
});
Edit 1
This is wrong.
.run(function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
});
You just need to inject $state into the controller you want to use it in.
angular.module('app').controller('Ctrl', ['$scope', '$state', function($scope,$state)
// Use $state here
$state.go('stateName');
{}]);
You forgot to inject ui.router, do that and it works fine.
https://jsfiddle.net/Christian_Schiffer/wLybswL9/1/
var myapp = angular.module('myapp', ['ui.bootstrap', 'ui.router']).config(function ($stateProvider, $urlRouterProvider) {
$stateProvider.state('one', {
url: '/',
templateUrl: '/one.html',
controller: 'MyCtrl'
})
$urlRouterProvider.otherwise('/');
}).run(function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
});
myapp.controller('MyCtrl', function ($scope) {
$scope.templateUrl = '/mobileTemplate.html';
});
myapp.controller('AccordionDemo', function ($scope) {
$scope.groups = [{
title: "Dynamic Group Header - 1",
routePath: "one.html",
number: 1,
current: true
}, {
title: "Dynamic Group Header - 2",
routePath: "two.html",
number: 2,
current: false
}];
});

How can I set the value of a $scope variable when my application starts up?

I have the following HTML:
<!doctype html>
<html lang="en" ng-class="theme">
<head>
...
</head>
<body>
<form>
<button class="white-gradient glossy" ng-click="theme = 'darkBlue'">Blue</button>
<button class="white-gradient glossy" ng-click="theme = 'black'">Black</button>
</form>
#Scripts.Render("~/bundles/Angular")
<script type="text/javascript">
angular.element(document).ready(function () {
angular.bootstrap(angular.element(document).find('html'), ['app']);
});
</script>
</body>
</html>
The buttons act as theme switchers to change my CSS and this works fine.
Here's my app.js
var app = angular
.module('app', ['ui.router', 'admin', 'home', 'questions', 'ngResource', 'LocalStorageModule'])
.config(['$locationProvider', '$sceProvider', '$stateProvider',
function ($locationProvider, $sceProvider, $stateProvider) {
$sceProvider.enabled(false);
$locationProvider.html5Mode(true);
var home = {
name: 'home',
url: '/home',
views: {
'menu': {
templateUrl: '/Content/app/home/partials/menu.html',
},
'content': {
templateUrl: '/Content/app/common/partials/empty.html',
}
}
}
$stateProvider
.state(home));
}])
.run(['$rootScope', '$scope', '$state', '$stateParams', function ($rootScope, $scope, $state, $stateParams) {
$scope.theme = 'darkBlue'
}])
.controller('appController', ['$scope', '$resource', '$state', function ($scope, $resource, $state) {
$scope.state = $state;
}]);
I am trying to set the default theme (line 2 of the HTML) at startup to 'darkBlue'.
However this does not seem to work. When my application starts the theme is not defined.
Can someone tell me what I am doing wrong and why it seems to ignore the line $scope.theme = 'darkBlue' ?
Note I also tried the following and this does not set the theme either:
.run(['$rootScope', '$state', '$stateParams', function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$state.transitionTo('home')
}])
.controller('appController', ['$scope', '$resource', '$state', function ($scope, $resource, $state) {
$scope.state = $state;
$scope.theme = 'darkBlue'
}]);
In your original example, you're injecting $scope into the run function
.run(['$rootScope', '$scope', '$state', '$stateParams', function ($rootScope, $scope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$state.transitionTo('home')
$scope.theme = 'darkBlue'
}])
but run cannot inject $scope because it isn't run against any particular view or controller. You can, however, inject $rootScope (as you already are) and set the data there:
.run(['$rootScope', '$scope', '$state', '$stateParams', function ($rootScope, $scope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$state.transitionTo('home')
$rootScope.theme = 'darkBlue'
}])
Prototypal inheritance will ensure that theme is available as a property on any child scope; however, you won't be able to change that value, because in JavaScript, writing to a property in this manner overwrites the property on the child object (e.g. setting $scope.theme in a controller would not propogate the change back up to the $rootScope, as you saw in your second example). See this wiki article for more information.
What you would most likely want to do is create a service to serve as the shared state between all the various places you want to access and change the data. You can find more information about services in the Developer Guide and as a video tutorial on egghead.io, but basically you can inject them into any number of controllers and the controllers share a single instance of the service. For example, it may look something like this:
<body>
<div ng-controller="ThemeController">
<form>
<button class="white-gradient glossy"
ng-click="theme.set('darkBlue')">Blue</button>
<button class="white-gradient glossy"
ng-click="theme.set('black')">Black</button>
</form>
</div>
#Scripts.Render("~/bundles/Angular")
#Scripts.Render("~/bundles/AngularApp")
<script type="text/javascript">
angular.element(document).ready(function () {
angular.bootstrap(angular.element(document).find('html'), ['app']);
});
</script>
</body>
Then, you can set up your service and inject it into controllers:
var app = angular
.factory('theme', function() {
var theme = null;
// every time you inject `theme`, it will inject the same instance
// of this object, which contains methods for getting and setting
// the current theme
return {
get: function() { return theme; },
set: function(t) { theme = t; }
};
})
// we can set the default theme in a `run` function
// by injecting it
.run(function(theme) {
theme.set('darkBlue');
})
// Here is the new `ThemeController` we created in the template, above
.controller('ThemeController', function($scope, theme) {
// bind `theme` to the scope so we can change it
$scope.theme = theme;
})
.config( // rest of app config
Working example: http://jsfiddle.net/BinaryMuse/bnAzp/

How do I add a controller to a module in Angular JS

I have the following in my app.js:
var app = angular.module('app', ['admin', 'ui.compat', 'ngResource', 'LocalStorageModule']);
app.config(['$stateProvider', '$locationProvider',
function ($stateProvider, $locationProvider) {
$locationProvider.html5Mode(true);
var home = {
name: 'home',
url: '/home',
views: {
'nav-sub': {
templateUrl: '/Content/app/home/partials/nav-sub.html',
}
}
};
$stateProvider.state(home)
}])
.run(['$rootScope', '$state', '$stateParams', function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$state.transitionTo('home');
}]);
in admin.js:
angular
.module('admin', ['ui.state'])
.config(['$stateProvider', '$locationProvider',
function ($stateProvider, $locationProvider) {
$locationProvider.html5Mode(true);
var admin = {
name: 'admin',
url: '/admin',
views: {
'nav-sub': {
templateUrl: '/Content/app/admin/partials/nav-sub.html',
}
}
};
var adminContent = {
name: 'admin.content',
parent: admin,
url: '/content', views: {
'grid#': {
templateUrl: '/Content/app/admin/partials/content.html',
controller: 'AdminContentController'
}
}
}
$stateProvider.state(admin).state(adminContent)
}])
I am confused about how to wire up my AdminContentController. Currently I have the following:
app.controller('AdminContentController',
['$scope', 'entityService', 'gridService', 'gridSelectService', 'localStorageService',
function ($scope, entityService, gridService, gridSelectService, localStorageService) {
$scope.entityType = 'Content';
Can someone verify if this is the correct way for me to set up my module and add it to app. Should I be adding the controller to the app:
app.controller('AdminContentController',
or should this belong to the module 'admin'. If it should then how should I wire it up?
Based on what you have shared, the the controller should be created on admin module such as
var adminModule=angular.module('admin'); // This syntax get the module
adminModule.controller('AdminContentController',
['$scope', 'entityService', 'gridService', 'gridSelectService', 'localStorageService',
function ($scope, entityService, gridService, gridSelectService, localStorageService) {
$scope.entityType = 'Content';
You could also define the controller in continuation of your admin module declaration.
Yes that would work angular.module('admin') works as a getter. So you'll get the same module in each file.

Resources