Nested states with parent's url == / - angularjs

If I have the following state:
$stateProvider
.state( 'home', {
url: '/',
views: {
'dashboard-body': {
templateUrl: './modules/main-dashboard.options.html',
controller: 'MainDashboardController',
controllerAs: 'vm'
}
}
} );
Can it have nested states?... I'm having trouble with it, I have the following states:
$stateProvider
.state( 'home', {
url: '/',
views: {
'dashboard-body': {
templateUrl: './modules/main-dashboard.options.html',
controller: 'MainDashboardController',
controllerAs: 'vm'
}
}
} )
.state( 'home.purchases', {
url: '/purchases',
views: {
'dashboard-body#home': {
templateUrl: './modules/purchases/purchases-dashboard.options.html',
controller: 'PurchasesDashboardController',
controllerAs: 'vm'
}
}
} );
But if i go to home.purchases state the url generated is: http://localhost:3000//purchases
If home.purchases has the property url like: url: 'purchases', it generates the right url http://localhost:3000/purchases but it doesnt't change the view... Any ideas?

If your root view (typically index.html) has the element with
ui-view="dashboard-body"
then your home.purchases state needs to reference that view using
views: {
'dashboard-body#': {
// ...
}
}
Otherwise, it's trying to load the template into a view named dashboard-body within the home state's template (modules/main-dashboard.options.html)

Related

Angular UI router; how to not match empty parameters

My website has 2 main routes:
/home
/:something
Any request to / should go to /home and this is done by using 'otherwise', anything else that does not match home AND is not empty should go to app.lista. The thing is, app.lista matches / because is like :slug is empty, so otherwise is not being called:
$stateProvider
.state('app', {
url: '/',
abstract: true,
templateUrl: '/_/common/templates/main.html',
controller: 'main'
})
.state('app.home', {
url: 'home',
views: {
sectionHolder: {
templateUrl: '/_/home/templates/home.html',
controller: 'home'
}
}
})
.state('app.lista', {
url: ':slug',
views: {
sectionHolder: {
templateUrl: '/_/home/templates/list.html',
controller: 'list'
}
}
});
$urlRouterProvider.otherwise('/home');
How can I tell the stateProvider to not match app.lista if :slug is empty?
Looks like same issue which is logged Here on github and solution seems to be the use ragular expression
I think changing your slug route to
.state('app.lista', {
url: '/{slag:[^\/]+}',
views: {
sectionHolder: {
templateUrl: '/_/home/templates/list.html',
controller: 'list'
}
}
});
Should solve your problem plunker
Make your app route non-abstract and change the template and controller to point to that of app.home. Since it is defined before app.list, '/' will match app route instead.
$stateProvider
.state('app', {
url: '/',
templateUrl: '/_/common/templates/home.html',
controller: 'home'
})
.state('app.home', {
url: 'home',
views: {
sectionHolder: {
templateUrl: '/_/home/templates/home.html',
controller: 'home'
}
}
})
.state('app.lista', {
url: ':slug',
views: {
sectionHolder: {
templateUrl: '/_/home/templates/list.html',
controller: 'list'
}
}
});
$urlRouterProvider.otherwise('/home');
Use UI Routers resolve to check if route params are missing.
//Example of a single route
.state('app.lista', {
url: '/:slug',
templateUrl: '----.html',
controller: 'list',
resolve: function($stateParams, $location){
//Check if url parameter is missing.
if ($stateParams.slug=== undefined) {
//Do something such as navigating to a different page.
$location.path('/somewhere/else');
}
}
})

Calling view of other state Angularjs

i am with doubt of like i call an view inside of other view. I want call the view " menu " in side of state "login" . However is not working
$stateProvider
.state('menu', {
abstract:true,
views: {
"menu": {
templateUrl: 'assets/templates/menu/menu.html',
controller: 'MenuController',
}
}
})
.state("login", {
url: '/login',
views: {
"": {
templateUrl: 'assets/templates/LoginTest.html',
controller: 'LoginController as ctrl',
},
"#menu":{ }
}
});
You need to use nested state for that.
This tutorial will help you AngularJS Multi-Step Form Using UI Router
working plunkr :https://plnkr.co/edit/ar9kbBCdggZxvUGDq5HI?p=preview
$stateProvider
.state('login', {
abstract:true,
url: '/login',
templateUrl: 'assets/templates/LoginTest.html',
controller: 'LoginController as ctrl'
})
// nested states
// each of these sections will have their own view
// url will be nested (/login/menu)
.state("login.menu", {
url: '/menu',
templateUrl: 'assets/templates/menu.html',
controller: 'MenuController'
}
);

switching layouts with angular ui-router

I try to use ui-router for switching between different layouts
$urlRouterProvider.otherwise('/');
$stateProvider
.state('root', {
url: '/',
views: {
'#': {
templateUrl: '_columnsTwo.html' // 2 columns
},
'main#root': {
templateUrl: 'content1.html',
controller: 'homeCtrl'
}
}
})
.state('data', {
url: '/du-lieu',
parent: 'root',
views: {
'main': {
templateUrl: 'content2.html',
controller: 'dataCtrl'
}
}
})
.state('oneCol', {
url: '/chi-tiet-tin',
views: {
'#': {
templateUrl: '_columnsOne.html' // one column layout
},
'detail#oneCol': {
templateUrl: 'contentOneCol.html'
}
}
})
});
Full code is at http://plnkr.co/edit/wGU6PaPAloCm33TDoGso?p=preview
Dont know why the state oneCol doesn't work.
In this case, it is usually a typo, Check this updated plunker: http://plnkr.co/edit/GygQZxEHogqcRS8vf1Bc?p=preview
The templateUrl: 'contentOneCol.html' was calling a template - which did not exist:
.state('oneCol', {
url: '/chi-tiet-tin',
views: {
'#': {
templateUrl: '_columnsOne.html' // one column layout
},
'detail#oneCol': {
templateUrl: 'contentOneCol.html' // this file was not there
} // there was one with suffix '.hml'
}
})
Because the file in the plunker was named
contentOneCol.hml // missing t
contentOneCol.html // correction I made

Same html page for different tabs in Angular UI Router

My angular app is routed as following:
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})
// Each tab has its own nav history stack:
.state('tab.dotnet', {
url: '/dotnet',
views: {
'tab-dotnet': {
templateUrl: 'templates/tab-dotnet.html',
controller: 'QuestionsCtrl'
}
}
})
.state('tab.sql', {
url: '/sql',
views: {
'tab-sql': {
templateUrl: 'templates/tab-sql.html',
controller: 'QuestionsCtrl'
}
}
})
The above two routes use the same controller but different html pages.
Since both the pages are same, I want to have a single html page in my application instead of two different tab-sql and tab-dotnet pages.
But I will need a differentiation variable to be injected to the controller when selecting the tabs.
Basically I need something like this:
.state('tab.dotnet', {
url: '/dotnet',
views: {
'tab-dotnet': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
type: 'dotnet' // so that i get this type in my Controller
}
}
})
.state('tab.sql', {
url: '/sql',
views: {
'tab-sql': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
type: 'sql'
}
}
})
How to achieve this?
You can pass data to controllers in a state using resolve.
.state('tab.dotnet', {
url: '/dotnet',
views: {
'tab-dotnet': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
resolve: {
type: 'dotnet';
}
}
}
})
.state('tab.sql', {
url: '/sql',
views: {
'tab-sql': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
resolve: {
type: 'sql';
}
}
}
})
https://github.com/angular-ui/ui-router/wiki#resolve

Angular: inheriting view in states

In Angular/Ionic i have three different states:
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('layout', {
url: "",
abstract: true,
templateUrl: "templates/base/layout.html"
})
.state('layout.home', {
url: "/home",
views: {
'mainContent' :{
templateUrl: "templates/home.html"
},
'leftMenuContent' :{
controller: "LeftMenuController",
templateUrl: "templates/left-menu.html"
}
}
})
.state('layout.about', {
url: "/about",
views: {
'mainContent' :{
templateUrl: "templates/about.html",
controller: "AboutController"
},
'leftMenuContent' :{
controller: "LeftMenuController",
templateUrl: "templates/left-menu.html"
}
}
})
So i have an abstract state which defines the base/main layout, home and about states which have two views: mainContent and leftMenuContent. As for the LeftMenuController functionality, it just returns custom options for every route depending the $state.current.name.
As leftMenuContent will be the same for every state, is there any way to avoid defining it in every new state and inheriting it from the layout state (or somewhere else) instead?
You are almost there: By calling the state layout.home it will inherit its views from layout, so this should work:
.state('layout', {
url: "",
abstract: true,
templateUrl: "templates/base/layout.html",
views: {
'leftMenuContent' :{
controller: "LeftMenuController",
templateUrl: "templates/left-menu.html"
}
}
})
.state('layout.home', {
url: "/home",
views: {
'mainContent' :{
templateUrl: "templates/home.html"
}
}
})
.state('layout.about', {
url: "/about",
views: {
'mainContent' :{
templateUrl: "templates/about.html",
controller: "AboutController"
}
}
})
This is what I found to be working to show nested views.
So, I have a main view in which I display my home template (<ui-view> in index.html), in the home template I have another <ui-view> in which I call different states based on what I want.
config(function config($stateProvider) {
$stateProvider
.state('sidemenu.home', {
url: '/home',
views: {
'topView': {
controller: 'HomeCtrl',
templateUrl: 'home/home.tpl.html'
}
}
})
.state('sidemenu.home.list', {
templateUrl: 'home/home-list.tpl.html'
/*,controller: 'HomeCtrl'*/
})
.state('sidemenu.home.login', {
templateUrl: 'home/home-login.tpl.html'
/*,controller: 'HomeCtrl'*/
})
.state('sidemenu.home.register', {
templateUrl: 'home/home-register.tpl.html'
/*,controller: 'HomeCtrl'*/
})
.state('sidemenu.home.coach', {
templateUrl: 'home/home-coach.tpl.html'
/*,controller: 'HomeCtrl'*/
})
;
})
.controller('HomeCtrl', function HomeController($scope, $rootScope, $state) {
/**
* ===== FIRST LOGIC =====
**/
//Redirect the user to the appropriate page.
switch ($rootScope.tellState()) {
case "ok-local":
$state.transitionTo('sidemenu.home.list');
break;
case "register":
$state.transitionTo('sidemenu.home.register');
break;
case "login":
$state.transitionTo('sidemenu.home.login');
break;
case "coach":
$state.transitionTo('sidemenu.home.coach');
break;
}

Resources