Angular UI-router switch between multi views to single view - angularjs

I have an app which has three views (ui-view using Angular ui-router):
header, sidebar and content.
my index.html looks like this: (I omitted the actual classes for clearness)
<body>
<div ui-view="header" class="..."></div>
<div class="page-container">
<div ui-view="sidebar" class="..."></div>
<div class="page-content">
<div ui-view="content"></div>
</div>
</div>
</div>
</body>
This pattern works well with pages that have the header and sidebar.
But I have some pages that I don't want to display the header and sidebar, for example a login page that should fit on all page.
For this kind of pages I need something like:
ui-view which should look like this:
<body>
<div ui-view="content"></div>
</body>
So it won't be nested and under the other views <div>'s and affected by their classes.
I have some solutions in mind, but none of them gave me a good enough UX.
I tried adding <ng hide> to the header and sidebar depending on the state. It worked but there was annoying flickering (that I couldn't eliminate with ng-cloak for some reason..)
To make things more clear, here is an example of two states , one is "one pager" and the other is full page with header and sidebar:
.state('Login', {
url: '/login',
views: {
'content': {
templateUrl: './../templates/login.html',
controller: 'LoginCtrl'
}
}
})
.state('Users', {
url: '/users',
views: {
'header': {
templateUrl: './../templates/header.html',
controller: 'HeaderCtrl'
},
'sidebar': {
templateUrl: './../templates/sidebar.html',
controller: 'SidebarCtrl'
},
'content': {
templateUrl: './../templates/users.html',
controller: 'UsersCtrl'
}
}
})
I also think using nested views, but not sure whether this is the right approach.

Maybe try using nested states, ie:
.state('app', {
url: '/app',
abstract: true,
templateUrl: './../templates/treeViewTemplate.html'
})
.state('login', {
url: '/login',
templateUrl: './../templates/login.html',
controller: 'LoginCtrl'
})
.state('app.users', {
url: '/users',
views: {
'header': {
templateUrl: './../templates/header.html',
controller: 'HeaderCtrl'
},
'sidebar': {
templateUrl: './../templates/sidebar.html',
controller: 'SidebarCtrl'
},
'content': {
templateUrl: './../templates/users.html',
controller: 'UsersCtrl'
}
}
})
In your root abstract state you define a template for 3 view-layout. login state will instead take whole display.

Related

How to display ui-router state on whole page?

I'm using ui-router for state handling. This works fine, but now I have to create page 404 and would like to display it on the whole page and not inside the page as other pages.
app.config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
function ($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.hashPrefix('!').html5Mode({
enabled: true,
requireBase: false
});
$stateProvider
.state('stateIndex', {
url: '/',
templateUrl: '/templates/list.html',
controller: 'dashListController'
})
.state('stateList', {
url: '/list',
templateUrl: '/templates/list.html',
controller: 'dashListController'
}).state('stateDashboard', {
url: '/dashboard/:id',
templateUrl: '/templates/dashboard.html',
controller: 'dashboardController'
})
.state('stateWidgetsList', {
url: '/widgetsList',
templateUrl: '/templates/widgetsList.html',
controller: 'widgetsListController'
})
.state('404', {
url: '/404',
templateUrl: '/templates/404.html'
});
}]);
and on my index.html I have
<div ui-view></div>
where I display all the pages, outside of this I have logo, menu, etc.. which I would like to hide while displaying 404 page.
How can I do it?
Personally I would redesign the index.html, and bring the outer template (logo, menu, etc), into it's own template and state. Then you can sit child states below it in the ui-router hierarchy. For example:
$stateProvider
.state('app', {
abstract: true,
url: '',
templateUrl: '/templates/appcontainer.html'
})
.state('app.stateIndex', {
url: '/',
templateUrl: '/templates/list.html',
controller: 'dashListController'
})
.state('404', {
url: '/404',
templateUrl: '/templates/404.html'
});
Then you just need to put your logos/menus, etc inside appcontainer.html, and then just have a single <div ui-view></div> inside your index.html. Also if you do it this way, don't forget to add the child ui-view inside appcontainer.html.
You can create a root parent state that will contain your layout stuff (logo, menu, etc) and have the 404 live outside of that.
routes
$stateProvider
.state('root', {
abstract: true, // makes this state not directly accessible
templateUrl: 'root.html'
})
.state('root.stateIndex', {
url: '/',
templateUrl: '/templates/list.html',
controller: 'dashListController'
})
// ...
.state('404', {
url: '/404',
templateUrl: '/templates/404.html'
});
root.html
<nav><!-- menu stuff --></nav>
<ui-view></ui-view>
<footer></footer>

Different states doesn't show template content

I have a basic Index.html file which following structure:
<body class="{{$state.current.name.replace('.','-')}}">
<div ui-view>
<div ng-include src="'partials/menu.html'"></div>
<!-- <div ng-menu class="ui top blue sidebar menu active"></div> -->
<div class="view-height-100"></div>
</div>
...
</body>
When I am in the login state, it's working very well:
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'partials/login-area.html',
controller: 'LoginController',
});
But, when I am routing to the user.management state, nothing gets shown (but Chrome is loading the template, so I can access the scope and the .html file is there):
$stateProvider
.state('user', {
url: '/:buildingName',
controller: 'CurrentBuildingController',
data: {
access: ['user']
}
})
.state('user.management', {
url: '/management',
templateUrl: '/views/management.html',
controller: 'ManagementController'
})
Can someone explain me why?
Parent state simply must have target for its child (unless we use absolute naming to target some super parent, but it is another approach)
.state('user', {
url: '/:buildingName',
template: "<div ui-view></div>",
controller: 'CurrentBuildingController',
data: {
access: ['user']
}
})
see that we now have template: "<div ui-view></div>", which will serve as a view target for any child state 'user.xxx'
Check also:
AngularJS UI-Router : Abstract state + child states not working
EXTEND - let child to target the index.html
We can use absolute naming and child will then be injected directly into index.html. There is a working plunker (by intention parent won't load, it does not have any template)
.state('parent', {
url: "/parent",
//templateUrl: 'tpl.html',
})
.state('parent.child', {
url: "/child",
views: {
'#': {
templateUrl: 'tpl.html',
controller: 'ChildCtrl',
}
}
})
Check this for more info:
Angularjs ui-router not reaching child controller

Is there a better way to go about building layouts using ui.router?

I am currently using <div ng-include src="'js/app/partials/layout/header.html'"></div> just above my <div ui-view> in my index.blade.php file while using Angular with Laravel.
I have looked into parent state inheritance in ui.router but it seems to not work, and feels complicated / or perhaps an overkill for layouts. I just want to inject a header and a footer.
This is what I was doing earlier in my attempt to use ui.router states to create a layout injection system. As you can see below.
<div ui-view="header"></div>
<div ui-view></div>
.state('root', {
url: '/',
abstract: true,
views: {
'header': {
templateUrl: 'js/app/partials/header.html'
}
},
data: {
requireLogin: false
}
})
.state('root.login', {
url: '/login',
templateUrl: 'js/app/partials/login.html',
controller: 'LoginCtrl',
data: {
requireLogin: false
}
})
You need to change your structure of your html, by making named views & those will be specified with templateUrl & controller from views option of the state.
Basically inside your home.html you would have three named views such as header, content & footer, root state is setting header & footer templates with controlllers. Then your child state login will set the content view by using absolute state name using content#root in this #root because content named view has been loaded inside root state.
Markup
<div ui-view="header"></div>
<div ui-view="content"></div>
<div ui-view="footer"></div>
Code
myApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/login');
$stateProvider
.state('root', {
abstract: true,
url: '/',
//templateUrl: 'js/app/partials/home.html',//remove this
views: {
'': {
templateUrl: 'js/app/partials/home.html' //add it here
},
'header': {
templateUrl: 'js/app/partials/header.html'
},
'footer': {
templateUrl: 'js/app/partials/header.html'
}
},
data: {
requireLogin: false
}
})
.state('root.login', {
url: 'login',
views: {
'content#root': {
templateUrl: 'js/app/partials/login.html',
controller: 'LoginCtrl',
},
},
data: {
requireLogin: false
}
})
});
Working Plunkr
I Think you use this.
`.state('header', {
abstract : true,
templateUrl: 'js/app/partials/header.html'
})
.state('home', {
url: '/',
templateUrl: 'js/app/partials/home.html',
parent : 'header',
data: {
requireLogin: false
}
})
.state('login', {
url: '/login',
parent : 'header',
templateUrl: 'js/app/partials/login.html',
controller: 'LoginCtrl',
data: {
requireLogin: false
}
})`

AngularJS UI Router nested view not loading content

I've looked at countless examples of how to set this up. Many right here at SO. But nothing is working in my case. It's a very simple set of two views, one nested below the first. Second ui-view never loads...
Here is the simple index.html...
<body ng-app="d6Games">
<div ui-view="home"></div>
</body>
Here is the simple child view, this is inside home.html template...
<div class="d6body bilbo">
<div ui-view="content"></div>
</div>
Here are the simple states...
.state('home', {
url: '/home',
views: {
'home': {
templateUrl: '/views/home.html'
}
}
})
.state('home.intro', {
url: '/intro',
views: {
'content': {
templateUrl: '/views/game-intro.html'
}
}
})
The first /views/home.html template loads fine, as expected, however the child /views/game-intro.html never loads. It's just html and text and it's in the same folder as home.html.
What am I missing?
There is a working plunker
I just changed the template path (removed the leading '/'), and all is working (however this was required for plunker, not sure about your environment and path settings):
$stateProvider
.state('home', {
url: '/home',
views: {
'home': {
templateUrl: 'views/home.html'
}
}
})
.state('home.intro', {
url: '/intro',
views: {
'content': {
templateUrl: 'views/game-intro.html'
}
}
})
}
Check that in action here

AngularJS ui-router: how can I have a fixed header with changing content?

I am trying to create a page where I have a fixed header and changing content, but the fixed header depends on the state route, I would also like the header and the content to have different controllers and templates.
For example for the URL
/user/:userId/profile
I would like the header to display the user name, so it needs to know the value of :userId.
I can achieve this by used named views and ui-router, but here us code duplication that I want to avoid
$stateProvider
.state('profile', {
url: '/user/:user_id/profile',
views: {
'header': {
templateUrl: 'user-header.html',
controller: 'HeaderController'
},
'info': {
templateUrl: 'profile.html',
controller: 'ProfileController'
}
}
})
.state('friends', {
url: '/user/:user_id/friends',
views: {
'header': {
templateUrl: 'user-header.html',
controller: 'HeaderController'
},
'info': {
templateUrl: 'friends.html',
controller: 'FriendsController'
}
}
})
<section id="startup-header" ui-view="header">
</section>
<section ui-view="info">
</section>
How can I define the header once, but have the content defined per content type.
I hope I formulate the questions in a way it's clear what I want to achieve.
Ok. Let's try this:
You can create a parent page with your header for user's profile that will be contain nested child pages:
<div id="header">
<a ui-sref="userPage.profile">Profile</a>
<a ui-sref="userPage.friends">Friends</a>
......
</div>
<div ui-view>
</div>
Read more about ui-sref ditective here
And in $stateProvider something like:
$stateProvider.state('userPage.profile', {
url: '/user/:user_id/profile',
templateUrl: 'profile.html',
controller: 'ProfileController'
}
}).state('friends', {
url: '/user/:user_id/friends',
templateUrl: 'friends.html',
controller: 'FriendsController'
}
})

Resources