I'm using angular-ui-router to load nested named views.
In the index.html file I have an unnamed view and a named one.
Index.html:
<div ui-view="header"></div>
<div ui-view=""></div>
I load header.html to named view header. The header view has two named views contactsSearch and countries.
Header.html:
<div ui-view="contactsSearch"></div>
<div ui-view="countries"></div>
In the unnamed view of the index.html file I want to load contacts.html.
Contacts.html:
Contacts List
I use three modules: myApp, countries and contacts. I've configured the routes for each module.
MyApp module:
angular.module('myApp', ['ui.state', 'contacts', 'countries'])
.config(['$stateProvider', '$routeProvider',
function ($stateProvider, $routeProvider) {
$stateProvider
.state("home",
{
url: "/home",
abstract: true,
views: {
'header': {
template: "<div class ='row' ui-view ='countriesList'></div><div class ='row' ui-view ='contactsSearch'></div>"
},
"": {
template: "<div ui-view></div>"
}
}
});
}]);
Countries module:
angular.module('countries', ['ui.state'])
.config(['$stateProvider', '$routeProvider',
function ($stateProvider, $routeProvider) {
$stateProvider
.state("home.countries", {
url: "/countries",
views: {
'countriesList': {
template: "<p>Countries</p>"
}
}
});
}])
.run(['$rootScope', '$state', '$stateParams', function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$state.transitionTo('home.countries');
}]);
Contacts module:
angular.module('contacts', ['ui.state'])
.config(['$stateProvider', '$routeProvider',
function ($stateProvider, $routeProvider) {
$stateProvider
.state("home.contacts", {//should be loaded to the unnamed view in index.html
url: "",
views: {
'contactsList': {
template: "<p>Contacts List</p>"
}
}
})
.state("home.contactsSearch", {
url: "/contactsSearch",
views: {
'contactsSearch': {
template: "<p>Contacts Search</p>"
}
}
});
}])
.run(['$rootScope', '$state', '$stateParams', function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$state.transitionTo('home.contactsSearch');
}]);
My code is not correct because nothing is being displayed and I cannot figure out why. After some investigation, I've found out that a parent can have only one state, but I need home.contacts, home.contactsSearch and home.countries to have the same parent: home.
Can someone please help me with this?
I've created a jsfiddle for more details: https://jsfiddle.net/cjtnmbjw/3/
Thank you
Related
Since updating npm to newest version, I have tried to maintain Angular 1.5.1, UI-Router 0.2.18 but it seems that nothing is rendering.
I need a layout where a top ui-view, nav, remains across several pages (eg, states). The page has a path variable containing the name of the state handed to it, which is the .run function attached.
Code (in .coffee)
angular.module('xxx', ['ui.router'])
.config([
'$stateProvider',
'$urlRouterProvider',
'$locationProvider',
'$sceProvider',
($stateProvider, $urlRouterProvider, $locationProvider, $sceProvider) ->
$sceProvider.enabled(false)
$urlRouterProvider.otherwise('/')
query = {
name: 'query',
url: '/query',
views: {
'nav#': {
templateUrl: 'nav/nav.html'
},
'main#query': {
templateUrl: 'query/query.html'
},
'builder#query': {
templateUrl: 'query/query-builder.html'
},
'result#query': {
templateUrl: 'query/query-result.html'
}
}
}
$stateProvider.state(query)
for r in ["a", "b", "c", "d", "e"]
query2 = {
name: r,
url: r,
views: {
'nav': {
templateUrl: 'nav/nav.html'
}
}
}
$stateProvider.state(query2)
])
.run([
'$rootScope',
'$state',
'$window',
'$timeout',
($rootScope, $state, $window, $timeout) ->
path = $window.path
if path
$state.transitionTo(path)
])
And related template files:
<ng-app="xxx">
<!-- Main base.html-->
<div ui-view="nav">
<!-- Specific query page -->
<div ui-view="main">
<!-- Within query page, nested ui-views -->
<div ui-view="builder"></div>
<div ui-view="result"></div>
Any thoughts?
Here is a documentation using nested views.
Here is a doc with the difference of route vs ui-route
As loading views nested to components and application, parent components will not load again in the below example the header. So the nav, remains across several pages.
Hope this is helpful.
function statesetup($stateProvider, $urlRouterProvider, $stateParams) {
console.log('Initiallizing State StartUp...');
$urlRouterProvider.otherwise('/');
$stateProvider
.state('main', {
url: '/',
template:
`
<header></header>
<div ui-view>I am init </div>
`
})
.state('main.a', { url: '/a',template: `<div>hi i am a </div>` })
.state('main.b', { url: '/b',template: `<div>hi i am b </div>` })
}
function run($rootScope, $location, $state) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
console.log('RootState Changed...');
var obj = {
event: event,
toState: toState,
toParams: toParams,
fromState: fromState,
fromParams: fromParams
};
return;
});
}
angular.module('xxx', ['ui.router'])
.component('header', {
template : `<ul>
<li ng-click="$ctrl.nav('main.a')">a</li>
<li ng-click="$ctrl.nav('main.b')">b</li>
</ul>`,
controller : function($state) { this.nav = (st) => $state.go(st); }
})
.config(['$stateProvider', '$urlRouterProvider', statesetup])
.run(["$rootScope", "$location", "$state", run])
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js"></script>
<div ng-app="xxx">
<div ui-view></div>
</div>
I have a problem, a Controller called OrderController standing on two modules, Sales and Supply. When I make the route that will use this controller as I can define which of the two controllers I want to use, how can I define which controller's module? I tried to register the route separately in each module, but still not the right.
Full code: https://plnkr.co/edit/iLUuUNKWZJhg23rrk1zB?p=preview
acmeModule.js
var app =
angular
.module('acme', [
// Angular UI
'ui.router',
// Acme modules
'acme.sales',
'acme.supply',
]);
app.config(config);
config.$inject = ['$stateProvider', '$urlRouterProvider'];
function config($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state("home", {
url: "/home",
template: "Home"
})
}
salesModule.js
var app =
angular
.module('acme.sales', ['ui.router']);
app.config(config);
config.$inject = ['$stateProvider', '$urlRouterProvider'];
function config($stateProvider, $urlRouterProvider) {
$stateProvider
.state("orderBySales", {
url: "/orderBySales",
templateUrl: "content.html",
controller: 'OrderController',
controllerAs: 'vm'
});
}
app.controller('OrderController', OrderController);
function OrderController() {
var vm = this;
vm.Content = "Order by Sales";
}
supplyModule.js
var app =
angular
.module('acme.supply', ['ui.router']);
app.config(config);
config.$inject = ['$stateProvider', '$urlRouterProvider'];
function config($stateProvider, $urlRouterProvider) {
$stateProvider
.state("orderBySupply", {
url: "/orderBySupply",
templateUrl: "content.html",
controller: 'OrderController',
controllerAs: 'vm'
});
}
app.controller('OrderController', OrderController);
function OrderController() {
var vm = this;
vm.Content = "Order by Supply";
}
You have to name the controller differently, otherwise one controller overwrites the other one. In this constellation (plunker) it is the controller of module acme.supply.
Call it SupplyOrderController and SalesOrderController.
I'm using ocLazyLoad with AngularJS and AngularJS UI Router to load AngualarJS modules on demand. I have a Posts view/state and Post view/state in different modules and I can simply navigate between them.
The only issue is that when I'm on /posts/1 and manually refresh the page, it goes back to /. I understand that it makes perfect sense because app.js is the only file that gets loaded after page refresh but what I don't understand is how to make it lazy load the same /posts/1 view again after refreshing the page. I tried using $urlRouterProvider.when in app.js but had no luck.
I have created a plunker for this: http://plnkr.co/edit/lPb2qCGF9KLL16jVoLQo?p=info
app.js
angular.module('app', ['ui.router', 'oc.lazyLoad'])
.run(['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.state = $state;
$rootScope.stateParams = $stateParams;
}
])
.config([
'$ocLazyLoadProvider',
'$stateProvider',
'$urlRouterProvider',
function ($ocLazyLoadProvider, $stateProvider, $urlRouterProvider) {
// For any unmatched url, redirect to /
$urlRouterProvider.otherwise('/');
$stateProvider
.state('app', {
url: '/',
views: {
header: {
template:
'<nav class="navbar navbar-default">' +
'<div class="container-fluid">' +
'<ul class="nav navbar-nav">' +
'<li><a ui-sref="app">Home</a></li>' +
'<li><a ui-sref="app.posts">Posts</a></li>' +
'</ul>' +
'</div>' +
'</nav>'
},
content: {
template: '<h3>Home view</h3>'
}
}
})
.state('app.posts', {
url: 'posts',
views: {
'content#': {
templateUrl: 'posts.html',
controller: 'PostsController',
resolve: {
load: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load({
serie: true,
files: [
'posts.js',
'posts-controller.js'
]
});
}]
}
}
}
});
}
]);
posts.js
angular.module('app.posts', ['ui.router', 'oc.lazyLoad'])
.config([
'$ocLazyLoadProvider',
'$stateProvider',
function ($ocLazyLoadProvider, $stateProvider) {
$stateProvider
.state('app.posts.post', {
url: '/:id',
views: {
post: {
templateUrl: 'post.html',
controller: 'PostController',
resolve: {
post: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load({
serie: true,
files: [
'post.js',
'post-controller.js'
]
});
}]
}
}
}
});
}
]);
post.js
angular.module('app.posts.post', []);
Lazy Loading ui-router states with ocLazyLoad and ui-router-extras futureStates
http://bardo.io/2014/08/26/oclazyload-future-states/
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>
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.