Different states doesn't show template content - angularjs

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

Related

Child states not working with UI-Router

I have the following code snippet:
$stateProvider.state('unlogged', {
url: '/',
templateUrl: 'unlogged/unlogged.html'
}).state('sign-in', {
parent: 'unlogged',
url: '/sign-in',
templateUrl: 'sign-in/sign-in.html',
controller: 'SignInCtrl'
}).state('sign-up', {
parent: 'unlogged',
url: '/sign-up',
templateUrl: 'sign-up/sign-up.html',
controller: 'SignUpCtrl'
});
When I go to /sign-up, it is not loading the parent nor the child.
My HTML when I inspect the page: <section ui-view="" class="ng-scope"></section>
unlogged.html has the ui-view directive: <div class="row" ng-class="{slide : effect}" ui-view></div>
There is a working example
To make child state url working without parent part, we need to reset that url mapping with a sign ^:
.state('sign-in', {
parent: 'unlogged',
url: '^/sign-in',
...
})
.state('sign-up', {
parent: 'unlogged',
url: '^/sign-up',
...
});
Check it in action here
Maybe also observe this:
angular ui-router parent url set to /

Angular UI-router switch between multi views to single view

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.

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

Angular UI-Router: child using parent's view

In story form:
What I am looking for here is a master-detail setup. The master is in list form and when I click on a link (relative to a particular row/record (or Account in this case)) I want to see the details in the main view (literally, the "main" view: <div class="container" ui-view="main"></div>).
I want to do this and maintain my URL structure (/accounts for the list of Accounts; /accounts/:id for the detailed version) but I want the detail view to use the view that the list was using.
What I currently have
index.html
...
<div class="container" ui-view="main"></div>
...
accounts.js
$stateProvider
.state ('accounts', {
url: '/accounts',
views: {
'main': {
controller: 'AccountsCtrl',
templateUrl: 'accounts/accounts.tpl.html'
}
},
data: { pageTitle: 'Account' }
})
.state ('accounts.detail', {
url: '/:id',
views: {
'main': {
controller: 'AccountDetailCtrl',
templateUrl: 'accounts/detail.tpl.html'
}
},
data: { pageTitle: 'Account Detail' }
});
At this point, the /accounts route works as expected. It displays accounts/accounts.tpl.html correctly in the main view. In that html each line in the repeater links it to its appropriate /accounts/:id URL, which I am handling with the nested state accounts.detail.
What is probably obvious to the majority of you who know more than me about this, my accounts.detail will render to the view main if that named view exists in the template accounts/accounts.tpl.html. That is indeed true.
But that is not what I want. I want the accounts.detail stuff to render in the parent main view; I want the html of accounts/detail.tpl.html to replace the html of accounts/accounts.tpl.html found in index.html: <div class="container" ui-view="main"></div>.
So how could I accomplish this?
MY SOLUTION IN CONTEXT
The trick is, as the answer says, to set up the URL scheme to identify which child state is "default". The way I interpret this code in plain English is that the parent class is abstract with the proper URL and the "default" child class has the "same" URL (indicated by '').
If you need further clarity, just post a comment and I'll share any more guidance.
.config(function config( $stateProvider ) { $stateProvider
.state ('accounts', {
abstract: true,
url: '/accounts',
views: {
'main': {
templateUrl: 'accounts/accounts.tpl.html',
controller: 'AccountsCtrl'
}
},
data: { pageTitle: 'Accounts' }
})
.state ('accounts.list', {
url: '',
views: {
'main': {
templateUrl: 'accounts/list.tpl.html',
controller: 'AccountsListCtrl'
}
},
data: { pageTitle: 'Accounts List' }
})
.state ('accounts.detail', {
url: '/:id',
views: {
'main': {
templateUrl: 'accounts/detail.tpl.html',
controller: 'AccountDetailCtrl'
}
},
data: { pageTitle: 'Account Detail' }
});
Sounds like you simply don't want the views to be hierarchical. To do this, simply change the name of the second state to detail.
Note however, that in doing so you will lose any hierarchical properties of the state tree (the controller code state of accounts for example).
If you want to keep the controllers hierarchical, but perform a replace of the html, I would create another parent above both others that takes care of the controller logic, but only has an extremely simple view <div ui-view=""></div>.
For example:
$stateProvider
.state('app', { url: '', abstract: true, template: 'parent.html', controller: 'ParentCtrl' })
.state('app.accounts', { url: '/accounts', templateUrl: 'accounts.tpl.html', controller: 'AccountsCtrl' })
.state('app.detail', { url: '/accounts/:id', templateUrl: 'detail.tpl.html', controller: 'AccountDetailCtrl' });
You can use '#' to define an absolute path to the ui-view of your choice. For example: "detail#contacts" : { }, where this absolutely targets the 'detail' view in the 'contacts' state. within contacts.html
Source: https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views

Nesting routes in Angular UI Router

(AngularJS v1.2.0-rc.3 + Angular UI-Router v0.2.0)
In my index.html, I have the following code:
<div class="container" ui-view></div>
In my app.js, I have the following code:
$stateProvider
.state('projects', {
abstract: true,
url: '/projects',
template: '<ui-view />',
})
// below display properly
.state('projects.list', {
url: '',
templateUrl: 'views/project_list.html',
controller: 'ProjectListCtrl'
})
// below display properly
.state('projects.one', {
url: '/{projectId:[0-9]{1,8}}',
templateUrl: 'views/project_dashboard.html',
controller: 'ProjectCtrl'
})
// below does not display at all
.state('projects.one.campaigns', {
url: '/campaigns',
template: 'I cannot seem to display this text'
})
I can hit the following routes just fine: index.html/projects, index.html/projects/1, but I cannot hit this route: index.html/projects/1/campaigns
Does anyone know why I can't?
Bonus points if you can answer how I could display the projects.one.campaigns state on the same URL page as the projects.one state.
The reason is because projects.one matches before projects.one.campaigns
Add a projects.one abstract state and then add a projects.one.default state with the templateUrl.
.state('projects.one', {
url: '/{projectId:[0-9]{1,8}}',
abstract:true,
template: '<ui-view/>',
})
.state('projects.one.default', {
url: '',
templateUrl: 'views/project_dashboard.html',
controller: 'ProjectCtrl'
})
.state('projects.one.campaigns', {
url: '/campaigns',
template: 'I cannot seem to display this text'
}
To display the template of the campaigns on the same page of the projects.one you should not use a state but a directive instead and toggle with ng-show on the same page.
I just spent whole day dealing with this problem.
I found out, that you don't need abstract states at all!
Try this:
index.html:
<div class="container"><ui-view/></div>
use directive ui-view as a tag in the top level template.
Now all your nested templates wrap like this:
<ui-view>
<div>
template code
</div>
</ui-view>
and now you can just:
$stateProvider
.state('list', {
url: '',
templateUrl: 'views/project_list.html',
controller: 'ProjectListCtrl'
})
// below display properly
.state('one', {
url: '/{projectId:[0-9]{1,8}}',
templateUrl: 'views/project_dashboard.html',
controller: 'ProjectCtrl'
})
// below does not display at all
.state('one.campaigns', {
url: '/campaigns',
template: 'I cannot seem to display this text'
})
I needed general solution for the nesting and this works. Now you can create very deep nesting easily (for example one.campaing.group.member.note). If you will use ui-view on the top level and wrap all templates with the ui-view, they contact of each template will replace content of the top level ui-view (which is empty).

Resources