I started building ionic app on top of the sidemenu starter app. The starter app has a base state 'app' which is abstract and all the sidemenu pages are children of the app for example app.search, app.browse, app.playlists etc.
I have similar hierarchy. However, I want the start page to be some other page, which means it is at the app level.
The states look like this:
$stateProvider
.state('app', {
url: "/app",
abstract: true,
templateUrl: "templates/menu.html",
controller: 'AppCtrl'
})
.state('join', {
url: "/join",
views: {
'menuContent' :{
templateUrl: "templates/join.html",
controller: 'joinCtrl'
}
}
})
.state('app.search', {
url: "/search",
views: {
'menuContent' :{
templateUrl: "templates/search.html",
controller: 'searchCtrl'
}
}
})
.state('app.results', {
url: "/results",
views: {
'menuContent' :{
templateUrl: "templates/results.html",
controller: 'resultsCtrl'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/join');
When I run the app, the url defaults to
http://192.168.1.4:8100/#/join
and shows a blank page. Obviously, the join.html is not blank. Also, the console.log messages in joinCtrl are not outputted.
I am not able to figure out why is it not loading the join page. When I change the otherwise to point to '/app/search', everything works.
Any idea what's going on? How do I load the initial page by default and then navigate to the 'app.search' state?
I would expect that because the app is abstract - it is there for a reason. To be parent/layout state. In its template should most likely live all other states.
If yes - check this working example I created to demonstrate that. What we need is to mark the join as a child of the app state. Then the 'menuContent' placeholder will be properly searched in the app template:
.state('join', {
parent: 'app',
url: "^/join",
views: {
'menuContent': {
templateUrl: "tpl.join.html",
controller: 'joinCtrl'
}
}
})
There is a working plunker
The definition url: "^/join", is there to support the idea, that the url defined like this:
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/join');
will work even for nested state (join is child of app). See:
Absolute Routes (^)
If you want to have absolute url matching, then you need to prefix your url string with a special symbol '^'.
This is just one way... we can do the similar stuff if the join is not nested state, but then it should target the unnmaed view '' instead of 'menuContent'
Related
I've created a starter app with side menu using Ionic based on AngularJS.
The basic navigation layout of the app suppose to be:
main page
ion-side-menu that shows our company's service types as a list. (when item is clicked go to:)
company services list for the chosen type (when item is clicked, go to:)
specific service view
Problem is that when I hit the auto-generated "Back" button from inside a specific service view, and expect to get back to the services list for the chosen type, the app does routes back to the list, he content is seen to about half a second, but then - ALL the content (including the top navbar) is hidden, and though, still clickable!
This also happens not just for the "Back" button but also when clicking a link from the specific service view to any arbitrary services list view.
Since the previous view is seen before disappearing, I conclude that the routing implementation is valid, but yet tried to use ui-route ui-sref and other approaches to navigation but couldn't solve this.
It happens both on chrome browser and android device.
My stateProvider config looks like that:
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'AppCtrl'
})
.state('app.main', {
url: '/main',
views: {
'menuContent': {
templateUrl: 'templates/main.html',
controller: 'MainCtrl'
}
}
})
.state('app.services', {
url: '/services/:tid',
views: {
'menuContent': {
templateUrl: 'templates/services.html',
controller: 'ServicesCtrl'
}
}
})
.state('app.service', {
url: '/service/:sid',
views: {
'menuContent': {
templateUrl: 'templates/service.html',
controller: 'ServiceCtrl'
}
}
})
Would really appreciate any help.
I have an angular app where I am using ui-router module. I am storing a "page" in database with URL and content. I also have some other states/URLs that have their own template. For example:
$stateProvider
.state('landing', {
url: '/',
templateUrl: 'landing-page.html'
})
.state('admin', {
url: '/admin',
templateUrl: 'admin.html'
})
.state('user', {
url: '/user',
templateUrl: 'user.html'
})
I want to define a state for the pages using something like
.state('page',{
url: '??',
templateUrl: 'page.html'
})
What should be in the url above if my page is dynamically stored in database with a URL/slug and content. How can I add the URL/slug here ? If I try this below:
.state('page', {
url: '/{path:.*}',
templateUrl: 'page.html'
})
Then it routes every page including the other states to the same template. I can always prefix the URL with something like /page but I don't want to do that. I want to be able to load the page as :
www.mysite.com/page-1
www.mysite.com/whatever-url
etc
Never mind. I figured this out. The trick was more about using regular expression. Here is my solution
.state('page', {
url: '/{path:(?!admin|user)[a-z0-9\-]+}',
templateUrl: 'page.html'
})
This will ignore routes starting with /admin and /user which we want first. Then, it will check if the url has at least 1 character.
Ok, here is the problem. I have an app where user can signup as merchant and can have their own store name and the url I looking for is:
http://localhost:8000/#/storename
This is getting conflict with default homepage subpages such as contactus, aboutus. Following is my implementation of ui-router.
.state('home', {
url: '/', --> http://localhost:8000/#/ [work]
templateUrl: 'views/main_home.html',
resolve: loadSequence('flexSlider','wantCtrl'),
css: 'assets/vendor/style.css'
})
.state('home.contact', {
url: '/contact', --> http://localhost:8000/#/contact [not work]
views: {
'homeView': {
templateUrl: 'partials/contact.html',
}
},
css: ['assets/vendor/style.css']
})
.state('store',{
url: '/:storename', --> http://localhost:8000/#/myshop [work]
templateUrl: 'views/main_store.html'
})
.state('store.list', {
url: '/lists', --> http://localhost:8000/#/myshop/lists [work]
views: {
'primView': {
templateUrl: 'views/store_home.html',
}
}
})
Here the http://localhost:8000/#/contact are accessing the store template as if contact is a store name. Default whatever inherit home.[anything] should be under parent defined template. How can i resolve this issue?
There is dirty way of doing this, which is define new parent for each of the subpages, but that will be repetition of header and footer partial layout.
as far as i know angular follows top to bottom approach while dealing with routes. so define
.state('store',{
url: '/:storename', --> http://localhost:8000/#/myshop [work]
templateUrl: 'views/main_store.html'
})
last after all other routes. In your case when angular reaches /:storename itwill think that contact is a store name and load that page. to avoid it you need to keep it last
I'm trying to migrate a native app to Ionic but I'm experiencing one major issue which is almost certainly a blocker if I can't at least work around it.
Basically, I have an application with multiple tabs and each of them has a split view. I attached a plunker to demonstrate what a simplified app version would look like. My problem is that when switching tab, ion nav views do not keep their history. To be more specific about my example: after selecting a playlist from the side menu and switching tab to "Search" and then back to "Playlists", the navigation history on that tab is not preserved and gets reset to its "root" state.
I think this happens when the ion-nav-view element is not a direct child of the ion-tab element (as in my case, since it's inside a ion-side-menu-content), but I'm not quite sure.
Overall, I feel the app states in the example might need some love as well. What am I doing anything wrong? Is it a known Ionic limitation?
State provider configuration follows, below is the link for the full plunker example:
$stateProvider
.state('tabs', {
url: '/app',
abstract: true,
templateUrl: 'tabs.html',
controller: 'AppCtrl'
})
.state('tabs.search', {
url: '/search',
views: {
'search': {
templateUrl: 'search.html'
}
}
})
.state('tabs.playlists', {
url: '/playlists',
views: {
'menu': {
templateUrl: 'playlists.html',
controller: 'PlaylistsCtrl'
},
'menuContent': {
templateUrl: 'empty.html'
}
}
})
.state('tabs.playlist', {
url: '/playlists/:playlistId',
views: {
'menu': {
templateUrl: 'playlists.html',
controller: 'PlaylistsCtrl'
},
'menuContent': {
templateUrl: 'playlist.html',
controller: 'PlaylistCtrl'
}
}
});
Here's a plunker with the app: http://plnkr.co/edit/UZp3EE3l6X5IIdvpu477
Thank you!
According to This other question, every time you navigate through a tab, it creates a new history, so there's no back. You would need to handle this with your own code. They propose to use the goBack() directly. Something like:
$ionicHistory.viewHistory().backView
Also, you would need to handle the case when there's no backView because you just logged in into the app.
I am using Angular UI Router , and I have setup two routes
One for all the content pages like /about, /terms etc
$stateProvider.state('sidebarPages.page', {
url: ':slug',
views : {
...
}
});
And now I want to add another for other pages like our-team
$stateProvider.state('sidebarPages.page', {
url: 'our-team',
views : {
...
}
});
The problem is that the second state is ignored when I go to page /our-team and the first one is executed instead which is :slug , and could accept everything.
Is there a way that I can create these two states, one for specific pages , and one that will accept everything and put it in slug param , and based on param I can then bring it from DB.
I created working plunker here. The order decides. Create states with known names, then the one with the slug:
// States
$stateProvider
.state('home', {
url: "/home",
templateUrl: 'tpl.html',
})
.state('other', {
url: "/other",
templateUrl: 'tpl.html',
})
.state('slug', {
url: "/:slug",
templateUrl: 'tpl.html',
})
;
Check it here