I have to create a page with a fixed top menu containing some input and buttons.
Depending on which data is filled in and which button is pressed, a map with data should appears below the menu.
The menu will always be there and only the map will be updated.
ROUTE
$stateProvider
.state('login', {
url : '/login',
templateUrl : 'app/login/login.html',
controller : 'LoginController'
})
.state('home', {
url : '/home',
templateUrl : 'app/home/home.html'
})
.state('menu', {
url : '',
templateUrl : 'app/menu/menu.html',
parent : 'home'
});
home.html
<div ui-view="menu"></div>
<h1 class="ui huge header">
Please select something
</h1>
For the moment I can only see the "Please select something" but not the menu.
After that, how can I replace "Please select something" by the needed map ? Is it possible to have a default view ? When landing on home I should see the message and not a map
EDIT
Here is what I got after the answers
ROUTE
$stateProvider
.state('login', {
url : '/login',
views : {
'login' : {
templateUrl : 'app/login/login.html',
controller : 'LoginController'
}
}
})
.state('home', {
url : '/home',
views : {
'menu' : {
templateUrl : 'app/menu/menu.html'
},
'content' : {
templateUrl : 'app/home/home.html',
}
}
})
.state('home.other', {
url : '/other',
views : {
'content#' : {
templateUrl : 'app/home/home.html'
}
}
});
INDEX.HTML
<div ui-view="login"></div>
<div ui-view="menu"></div>
<div ui-view="content"></div>
It is working well but it is the best way to do it ? I have a lot of different content so I will have to duplicate the menu view inside every state ?
If I have a page with a different layout (without menu and content) - Should I just add a new <div ui-view="list"></div> in index.html ?
EDITED according to question update
Try to read Nested views this article to better understand existing solution in ui-router.
Here is example what you can do to avoid duplication of routes:
$stateProvider
.state('login', {
url: '/login',
views: {
'login': {
templateUrl: 'app/login/login.html',
controller: 'LoginController'
}
}
})
.state('menu', {
url: '/menu',
templateUrl: 'app/menu/menu.html'
})
.state('menu.content', {
views: {
'default': {
url: '/default',
template: '<h1>Please select something</h1>'
},
'content1': {
url: '/content1',
templateUrl: 'app/content1/content1.html'
},
'content2': {
url: '/content2',
templateUrl: 'app/content2/content2.html'
}
}
});
As you can see very clear to read and understand from url what is inside and why. If you will have url menu/content1 - that's mean under your menu is content1 visible right now.
You don't have to define another state for the the menu just add it to your home state as another view. Like this
.state('home', {
url: '/home',
views:{
'menu': {
templateUrl: 'app/menu/menu.html'
},
'home': {
templateUrl: 'app/home/home.html'
}
}
})
And change your HTML to this:
<div ui-view="menu"></div>
<div ui-view="home"></div>
And whenever you want to update the view (keeping the menu the same), create a state for that view like this:
.state('home.newState', {
url: '/newState',
views:{
'home#':{
templateUrl: 'app/home/newState.html'
}
}
})
This will update the view by adding the newState.html template in place of home.html template keeping the menu same.
Related
I'm trying to render templates inside a main view. Here is the Feed, which is my main view.
<ion-view view-title="Feed">
<ion-content scroll="true">
<div ui-view="opportunity"></div>
</ion-content>
</ion-view>
I'm trying to render Opportunity inside my Feed. Here is the code for Opportunity. The template is named as card-opportunity.html
<h1>Opportunity Details</h1>
In the app.js I have included the views for opportunity. I'm using $stateProvider
$stateProvider
.state('app.feed', {
url: '/feed',
views: {
'menuContent': {
templateUrl: 'templates/feed.html',
controller: 'FeedCtrl'
},
'network' : {
templateUrl: 'templates/card-network.html',
controller: 'CardNetworkCtrl'
},
'opportunity' : {
templateUrl: 'templates/card-opportunity.html',
controller: 'CardOpportunityCtrl'
}
}
});
Not sure what I'm missing. There is no error in the console. I'm using ionic: 3.7.0
https://github.com/angular-ui/ui-router/wiki/Nested-States-and-Nested-Views
says this:-
"Child states will load their templates into their parent's ui-view."
I am not sure if a view will load if you give its ui-sref in its sibling view. Why don't you create a new state for the opportunity ,so that it loads as a child of the feed.
$stateProvider
.state('app.feed', {
url: '/feed',
views: {
'menuContent': {
templateUrl: 'templates/feed.html',
controller: 'FeedCtrl'
},
'network' : {
templateUrl: 'templates/card-network.html',
controller: 'CardNetworkCtrl'
}
}
})
.state('app.feed.opportunity',{
url: '/opportunity',
views: {
'opportunity' : {
templateUrl: 'templates/card-opportunity.html',
controller: 'CardOpportunityCtrl'
}
}
});
If I have index.html with:
<body>
<ui-view="home"></home>
</body>
Then inside that home view i render frame.html with the following inside:
<div ui-view="home_content"></div>
In my app.js I've been trying to get the most inner the ui-view inside frame.html to render another html template. I'm able to render the content in the home view just fine but nothing renders inside home_content.
My app.js ui-router code
$stateProvider
.state('user', {
abstract: true,
template: '<ui-view/>',
data: {
access: AccessLevels.user
}
})
.state('user.home', {
url: '/home',
views: {
'home#': {
templateUrl: 'app/partials/home/frame.html',
controller: 'homeCtrl'
},
'home_content#home': {
templateUrl: 'app/partials/home/dashboard/index.html',
controller: 'dashboardCtrl'
}
}
});
Seems like I may be coming at this all wrong, not sure if the above is the right way to go about it.
There is a working plunker
I would expect, that you want to target unnamed view of your parent in the child, so the view should be defined like this:
$stateProvider
// here we define parent
.state('user', {
abstract: true,
// parent has UNNAMED view
template: '<ui-view/>', // this will be injected into index.html
... // ui-view=""
})
// child will partilly target parent
// and also itself
.state('user.home', {
url: '/home',
views: {
// here we target parent UNNAMED view
'': {
...
},
// here we target current state
// so we should use state name
'home_content#user.home': {
...
}
}
});
What would also work is instead of '' : { } we can use '#home' : {} (see the doc below).
In case (as mentioned below in the comment) we have index.html with target named home:
<div ui-view="home"></div>
We can use this plunker, which redefines the parent abstract state like this:
$stateProvider
.state('user', {
abstract: true,
data: {
...
},
views : {
'home' : {
template: '<div ui-view=""></div>',
}
}
})
Check the doc
View Names - Relative vs. Absolute Names
Behind the scenes, every view gets assigned an absolute name that follows a scheme of viewname#statename, where viewname is the name used in the view directive and state name is the state's absolute name, e.g. contact.item. You can also choose to write your view names in the absolute syntax.
For example, the previous example could also be written as:
.state('report',{
views: {
'filters#': { },
'tabledata#': { },
'graph#': { }
}
})
Looks like your child .state has wrong code it should be 'home#home_content' instead of 'home_content#home'
.state('user.home', {
url: '/home',
views: {
'': {
templateUrl: 'app/partials/home/frame.html',
controller: 'homeCtrl'
},
'home#home_content': {
templateUrl: 'app/partials/home/dashboard/index.html',
controller: 'dashboardCtrl'
}
}
});
You are making your state configuration complex. Just change your code to look like this:
$stateProvider.state('user', {
abstract : true,
template : '<ui-view/>',
data : {
access : AccessLevels.user
}
})
.state('user.home', {
url : '/home',
views : {
'home' : {
templateUrl : 'app/partials/home/frame.html',
controller : 'homeCtrl'
},
'home_content' : {
templateUrl : 'app/partials/home/dashboard/index.html',
controller : 'dashboardCtrl'
}
}
});
You are actually not using # properly and which is optional. This should work unless you have your correct view path.
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
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'
}
})
I am writing an AngularJS Application using ui-router. The states 'home' and 'book' are loaded into the (parent) - ui-view element
My setup for the routes is as following :
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home2/app'
})
.state('book', {
url: '/book',
templateUrl: '/book/index'
})
.state('book.overview', {
url: '/overview',
templateUrl: '/book/overview'
})
.state('book.edit', {
url: '/edit/:bookid',
templateUrl: '/book/detail',
controller: 'bookeditcontroller'
})
.state('book.create', {
url: '/create',
templateUrl: '/book/detail',
controller: 'bookeditcontroller'
});
});
When the user tiggers the 'book' state (through a href), the template from '/book/index' is loaded and displayed successfully. But on this first request, i also want to load the template from '/book/overview' and displaying it in the child ui-view.
i've already read the topics about the default states under https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-set-up-a-defaultindex-child-state
But this is not exactly the behavior i want. Is there a way to tell ui-router when parent state 'book' is loaded, also load 'book.overview' into its (child) ui-view ?
Thanks for you help!
I would say that you will need
Multiple Named Views
This allows us to think in one state - many views
State would look like this
.state('book', {
url: '/book',
views : {
'' : { templateUrl: '/book/index', },
'#book': {templateUrl: '/book/overview' },
}
})
this way, we will place two views into one state.
The first will be injected into index.html/root <div ui-view=""></div>
The second will be placed inside of the templateUrl: '/book/index',
That's how we can play with many views in one (or even more parent, grand parent...) state.
I created a plunker with layout, which does show a bit similar example. The code snippet of the state with many views is:
$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',},
},
})