angularjs toggle $stateProvider views based on viewport - angularjs

I have a view with 3 nested views, when the viewport is less than 768 I want to hide 2 of the 3 nested views and toggle between the three. What is the best method to toggle nested views with $stateProvider, I've been looking around but getting mixed answers.
I am using jade/coffeescript.
.state 'messages',
url: '/messages',
views:
'':
templateUrl: 'views/messages.html',
controller: 'MessagesCtrl'
'ticketList#messages':
templateUrl: 'views/messages/list.html'
'ticketComments#messages' :
templateUrl: '/views/messages/comments.html'
'ticketDetail#messages' :
templateUrl: '/views/messages/detail.html'
and the main view:
div(ui-view="ticketList")
div(ui-view="ticketComments")
div(ui-view="ticketDetail")

Related

UI-Router should only change partial

I'm building an angular application using ui-router, and there's one thing I can't figure out.
There's a sidebar on the left, and a content area. Both are controlled by own controllers. When I choose an item in the sidebar, the content area shall be updated, but the sidebar must remain its state. What it does instead is that the sidebar reloads as well when selected an item.
app.coffee:
$urlRouterProvider.otherwise "/items/near/map"
$stateProvider
.state('items',
url: '/items'
abstract: true
templateUrl: "items.html"
)
.state('items.near',
url: '/near'
abstract: true
views:
'sidebar#items':
templateUrl: 'items-near-list.html'
controller: 'ItemsNearListCtrl'
)
.state('items.near.map',
url: '/map'
views:
'content#items':
templateUrl: 'items-near-map.html'
controller: 'ItemsNearMapCtrl'
)
.state('items.near.detail',
url: '/detail/:id'
views:
'content#items':
templateUrl: 'item-detail.html'
controller: 'ItemsNearDetailCtrl'
)
items.html:
<div>
<div ui-view="sidebar"></div>
<div ui-view="content"></div>
</div>
A probably related problem it that if I enter a detail view state directly (/items/near/detail/x/), the sidebar does not even load anything. Any idea what I'm doing wrong?
Hmm I never used the absolute # syntax for the view names but after looking into the docs it seems this may be the problem.
Please try without the #items or use the full state/view-combination like sidebar#items.near, content#items.near.map and content#items.near.detail.

optional parameters in ui.router url

I am trying to show the same view regardless of whether the :id parameter is set in the url. I have this but the /cases route doesn't seem to work without the :id.
.state 'messages',
url: '/cases',
views:
'':
templateUrl: 'views/messages.html',
controller: 'MessagesCtrl'
'ticketList#messages':
templateUrl: 'views/messages/list.html'
'ticketComments#messages' :
templateUrl: '/views/messages/comments.html'
'ticketDetail#messages' :
templateUrl: '/views/messages/detail.html',
.state 'messages.id',
url: '/cases/:id',
views:
'':
templateUrl: 'views/messages.html',
controller: 'MessagesCtrl'
'ticketList#messages':
templateUrl: 'views/messages/list.html'
'ticketComments#messages' :
templateUrl: '/views/messages/comments.html'
'ticketDetail#messages' :
templateUrl: '/views/messages/detail.html',
You are almost there - just child inherits url from its parent. So to make just cases working, we should do:
.state 'messages',
url: '/cases',
....
.state 'messages.id',
// url: '/cases/:id', // instead of this
url: '/:id', // we need this
And we can do even more, e.g. use params :{} to define more precise settings. Check these for example:
Angular ui router passing data between states without URL
Angular js - route-ui add default parmeter
Prepend optional attribute in angular ui-router URL
Angular UI-Router more Optional Parameters in one State

Nested states or views for layout with leftbar in ui-router?

I have the following layout:
Sidebar and Headerbar will always be present though their content is context-specific.
I think there are two options here: nested states (sidenav > Headerbar > Content) or with views (if I understand that correctly). I'm still struggling to get my head wrapped around ui-router regardless of how many videos and articles I've read.
Clicking on Sidenav would load a state (or view) into Content and Headerbar would adjust its content based on whatever is loaded into Content.
My sense is that nested states seem like the simplest direct approach, particularly when thinking about inheritance.
Looking at it from another point of view, these seem like they could be siblings (although inheritance issues probably make me wrong). My inkling is that views would allow me more flexibility in the future with sub-items and such.
And of course ng-include and directives could play into this.
Being new to ui-router could someone slap me in the right direction? Where I'm stuck is loading the home view. I want my users to see their dashboard in the Content section once they log in. And then, how do I load new elements into Content as the user navigates from the Sidebar?
One way how to design scenario with 1) side bar, 2) action section and 3) main area could be like in this working example
Firstly the root state. Here is root state named 'index'. It is abstract and could do some resolve for us. It does not effect child state naming and does not extend the url (because is undefined)
$stateProvider
.state('index', {
abstract: true,
//url: '/',
views: {
'#' : {
templateUrl: 'layout.html',
controller: 'IndexCtrl'
},
'top#index' : { templateUrl: 'tpl.top.html',},
'left#index' : { templateUrl: 'tpl.left.html',},
'main#index' : { templateUrl: 'tpl.main.html',},
},
})
The first real state is list, and it inherits from parent but with an attribute parent: 'index', so the parent name is not effecting the state name.
Advantage is, that it could inherit lot of resolved stuff. Also, the root state could be loaded once, for all other parent states
.state('list', {
parent: 'index',
url: '/list',
templateUrl: 'list.html',
controller: 'ListCtrl'
})
This is the real power of UI-Router, because now we can see that child is injecting stuff into two places - 1) action section and 2) main area
.state('list.detail', {
url: '/:id',
views: {
'detail#index' : {
templateUrl: 'detail.html',
controller: 'DetailCtrl'
},
'actions#index' : {
templateUrl: 'actions.html',
controller: 'ActionCtrl'
},
},
})
This way, we can use named views and multi views in real world scenario. Please, never forget how the scope definition goes:
Scope Inheritance by View Hierarchy Only
Keep in mind that scope properties only inherit down the state chain if the views of your states are nested. Inheritance of scope properties has nothing to do with the nesting of your states and everything to do with the nesting of your views (templates).
It is entirely possible that you have nested states whose templates populate ui-views at various non-nested locations within your site. In this scenario you cannot expect to access the scope variables of parent state views within the views of children states.
Check that all in action here
I just would like to share my experience. There is
similar Q & A: Angular UI Router - Nested States with multiple layouts
and a link to working plunker
The snippet of the state def:
$stateProvider
.state('index', {
url: '/',
views: {
'#' : {
templateUrl: 'layout.html',
controller: 'IndexCtrl'
},
'top#index' : { templateUrl: 'tpl.top.html',},
'left#index' : { templateUrl: 'tpl.left.html',},
'main#index' : { templateUrl: 'tpl.main.html',},
},
})
.state('index.list', {
url: '/list',
templateUrl: 'list.html',
controller: 'ListCtrl'
})
.state('index.list.detail', {
url: '/:id',
views: {
'detail#index' : {
templateUrl: 'detail.html',
controller: 'DetailCtrl'
},
}
In a nutshell, I do use the nesting approach.
It is similar to the "core example" available here http://angular-ui.github.io/ui-router/sample/#/. It is hierarchical (entity list / detail)
And what's more, I use the hidden supper root state:
check the details here Updating resolved objects in ui.router parent states
the examle link
which is handling security related stuff - once, and shared among all child states:
$stateProvider
.state('root', {
abstract: true,
template: '<div ui-view></div>',
resolve: {objectX : function() { return {x : 'x', y : 'y'};}},
controller: 'rootController',
})
.state('home', {
parent: "root",
url: '/home',
templateUrl: 'tpl.example.html',
})
.state('search', {
parent: "root",
url: '/search',
templateUrl: 'tpl.example.html',
})
Hope it does enlighten this a bit, because the power of UI-Router I see in multiviews, view nesting, scope inheritance and the logical state machine behind

AngularJS ui-router with different URL parameters

While using ui-view in AngularJS, I'm trying to use URL parameters inside of nested views.
For entities of a given type, I want to be able to show all of the entities when navigating to the url /entities, but I would also like to see only the entities of a given type if I go to entities/ofcategory/categoryName. Lastly, I also want to be able to navigate to /entities/details/entityName to see the details of one entity.
Is this structure possible?
This is my ui-routercode:
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('entities', {
url: '/entities',
templateUrl: 'app/entities/views/entities.html'
})
.state('entities.ofcategory', {
url: '/ofcategory/:categoryName',
templateUrl: 'app/entities/views/entities.ofcategory.html'
}
.state('entities.details', {
url: '/details/:entityName',
templateUrl: 'app/entities/views/entities.details.html'
});
}]);
If I'm navigating to entities/ofcategory/aname or /entities/details/aname I enter the regular entities controller instead of the category or detailsController
One option is to add an abstract state, which serves as a parent to all your entities states. In that case all your urls become relative to this parent state. Please note that you have to define a ui-view in the template of the abstract state, so it could be used for loading the child templates.
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('entities', {
url: '/entities',
abstract: true,
templateUrl: 'app/entities/views/entities.html'
})
.state('entities.all', {
url: '/',
templateUrl: 'app/entities/views/entities.all.html'
})
.state('entities.ofcategory', {
url: '/:categoryName',
templateUrl: 'app/entities/views/entities.ofcategory.html'
}
.state('entities.details', {
url: '/details/:entityName',
templateUrl: 'app/entities/views/entities.details.html'
});
}]);
app/entities/views/entities.html:
<div>
<h1>Entities<h1>
<div ui-view></div>
</div>

angularJS nested abstract views

I am using StateProvider library to create nested views in my AngularJS app.
I had an abstract view defined at the root and now need to define another abstract view as 2nd level child to the previously created abstract view.
Facing issues with this, Not sure if I can have nested abstract views or not. Any idea.
greatly appreciate your help.
Thanks
There could be more abstract-nested states in hierarchy. This example shows it in action, definition of these states could be like this:
$stateProvider
.state('main', {
url: "",
abstract: true,
templateUrl: 'tpl.main.html',
})
.state('main.middle', {
url: "",
abstract: true,
templateUrl: 'tpl.middle.html',
})
.state('main.middle.alpha', {
url: "/alpha",
templateUrl: 'tpl.leaf.html',
controller: function ($scope, $state){
$scope.state = $state.current;
},
})
Check the plunker. As we can see, the root (main) and its child (middle) do not use url at all... but they could..

Resources