I've <user />, an angular.component that is a user's profile page that includes 4 tabs, like this:
Using ui-router I show a different template depending on the selected tab in the ion-tabs (details/followers/following/photos)
My problem is: when I click the back button it navigates also between the child views (home.user.details, home.user.followers, ...) instead of going directly to the previous view (e.g. home)
The best solution I can think about is to pass the previous views's name as parameter to home.user, this way I get the right prev view but I can't see it in <user />'s controller
.state('home.user', {
url: '/user/:id',
abstract: false,
cache: true,
template: '<user></user>',
resolve: {
id: function($stateParams) {
return $stateParams.id;
},
prev: function($ionicHistory) {
return $ionicHistory.currentView()
}
}
})
.state('home.user.details', {
url: '/details',
templateUrl: 'template/user.details.html'
})
.state('home.user.followers', {
url: '/followers',
templateUrl: 'template/user.followers.html'
})
// Same for home.user.following and home.user.photos
How can I pass prev to <user />?
Is there a better way to solve my navigation problem?
EDIT
These are the tabs in <user />'s template:
<ion-tabs>
<ion-tab ui-sref="home.user.details">
</ion-tab>
<ion-tab ui-sref="home.user.followers">
</ion-tab>
</ion-tabs>
<ion-nav-view class="inner-view"></ion-nav-view>
Related
Is it possible to link from one tab to a nested view in another tab? I've tried two different methods and neither seem to work.
Here's my router config:
.config(function($stateProvider, $urlRouterProvider) {
// Ionic uses AngularUI Router which uses the concept of states
// Learn more here: https://github.com/angular-ui/ui-router
// Set up the various states which the app can be in.
// Each state's controller can be found in controllers.js
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
// Each tab has its own nav history stack:
.state('tab.dash', {
url: '/dash',
views: {
'tab-dash': {
templateUrl: 'templates/tab-dash.html',
controller: 'DashCtrl'
}
}
})
.state('tab.chats', {
url: '/chats',
views: {
'tab-chats': {
templateUrl: 'templates/tab-chats.html',
controller: 'ChatsCtrl'
}
}
})
.state('tab.chat-detail', {
url: '/chats/:chatId',
views: {
'tab-chats': {
templateUrl: 'templates/chat-detail.html',
controller: 'ChatDetailCtrl'
}
}
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tab/dash');
});
In templates/tab-dash.html I have a link to a particular chat detail page:
<ion-view view-title="Dashboard">
<ion-content class="padding">
<h1>My Chats</h1>
Chat #1
</ion-content>
</ion-view>
From here I can navigate the chat detail page, however if I click the "Chats" tab button at the bottom nothing at all happens. I'd like it to bring me to the main Chats page.
Another method I tried was using ui-sref instead of href:
<ion-view view-title="Dashboard">
<ion-content class="padding">
<h1>My Chats</h1>
<a ui-sref="tab.chat-detail{chatId:1}">Chat #1</a>
</ion-content>
</ion-view>
In this case I receive an error Could not resolve 'tab.chat-detail{chatId:1}' from state 'tab.dash'
What's the best way to link to a "detail" view from within another tab? My main is to make sure that clicking the tab button at the bottom always brings me to the parent page for that tab. Right now, in the first example, it gets stuck on the "detail" view.
I got a workaround. I am hiding the tab bar when navigating to nested view of another tab.
And showing it again when user navigates back to the root tab.
To know how to hide and show tab bar programmatically, check this link:-
https://stackoverflow.com/a/45002644/4527624
My abstract state is a frame with tabs that loads in the lower section a template depending on the active tab. The layout is similar to this:
The problem is that when I navigate back it also navigates through the tabs, instead of going to the previous state. How can I prevent this behaviour?
This is the template of my parent state
<ion-tabs>
<ion-tab ui-sref="home.user.details">
</ion-tab>
<ion-tab ui-sref="home.user.followers">
</ion-tab>
</ion-tabs>
<ion-nav-view class="inner-view"></ion-nav-view>
And this is my ui-router configuration
.state('home.user', {
url: '/user/:id',
abstract: false,
cache: true,
template: '<user></user>',
resolve: {
id: function($stateParams) {
return $stateParams.id;
}
}
})
.state('home.user.details', {
url: '/details',
templateUrl: 'template/user.details.html'
})
.state('home.user.followers', {
url: '/followers',
templateUrl: 'template/user.followers.html'
})
If you want to do this when the hardware backbutton is used you could do it with Ionic's onHardwareBackButton feature by manually setting the state where it should navigate to like this:
$ionicPlatform.onHardwareBackButton(onBackButton);
function onBackButton(e) {
$state.go('home.user');
}
You can register the above on the tab states and then remove it with offHardwareBackButton when the wanted behaviour changes like this:
$ionicPlatform.offHardwareBackButton(onBackButton);
I didn't see a back button but if you do have/want one replace it with a self made on and make it go to the parent state with something like this:
HTML:
<button class="button" ng-click="goToHome()">
<i class="icon ion-android-arrow-back"></i>
</button>
Controller:
$scope.goToHome = function() {
$state.go('home.user');
};
I have this in my app.js:
.state('tab.interview', {
url: '/interview/:survey_id',
views: {
'tab.interview': {
templateUrl: 'templates/tab.interview.html',
controller: 'interviewController'
}
},
resolve: {
duh: function() {
console.log('HOHOHO');
return new Date();
}
}
})
I have this in my tabs.html:
<ion-tabs class="tabs-icon-top tabs-color-active-positive">
<ion-tab title="Organizer" icon-off="ion-ios-list-outline" icon-on="ion-ios-list" ui-sref="tab.survey">
<ion-nav-view name="tab.survey"></ion-nav-view>
</ion-tab>
<ion-tab title="Interview" icon-off="ion-chatbox" icon-on="ion-chatbox-working" ui-sref="tab.interview" ui-sref-opts="{reload: true, inherit: false}">
<ion-nav-view name="tab.interview"></ion-nav-view>
</ion-tab>
</ion-tabs>
You can see that I already have this options for the tab: ui-sref-opts="{reload: true, inherit: false}" . I thought it would force the reload of the controller, along with its resolve dependencies.
I have a controller like this:
$scope.$on('$ionicView.enter', function() {
console.log('.....');
console.log(duh);
console.log('.....');
});
What I'm seeing in the console is:
HOHOHO gets printed everytime I switch to that tab. This tells me new instance of "duh" dependency is created.
But... the console.log in the ionic.enter gives me the same value (the time the _first_time_ I load that tab). E.g.: Mon Dec 28 2015 08:26:02 GMT-0600. Always that same value. As if the newly created instance of duh (Date) was not (re)bound to that variable in the controller.
Where did I do wrong? It is essential for my app that the duh is refreshed everytime I switch to that tab (particular when the "reload" options in the $state.go is set to true).
Thanks in advance,
Raka
You can disable the cache for the given state:
.state('tab.interview', {
cache: false,
url: '/interview/:survey_id',
views: {
'tab.interview': {
templateUrl: 'templates/tab.interview.html',
controller: 'interviewController'
}
},
resolve: {
duh: function() {
console.log('HOHOHO');
return new Date();
}
}
})
I'm developing my first application. It have worked really good, but now I'm stuck with an issue related to $stateParams.
I'm developing an app which requires login and logout. And have a url in this format:
'#/tab/profile/{{userId}}'
I have a tab to show the user profile. It should read the ID from the url, and render this user.
If I login with an user, the profile is rendered correctly. But when I log out and then log in with other user, It still shows the first user profile. The $stateProvider variable, it still have the previous value.
I recorded this short video to explain my problem.
https://youtu.be/d4U1j3gKKt4
And below is my source code.
This is really driving me crazy. What should I do? Thanks a lot!
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('tab.profile', {
url: '/profile/:userIdInUrl',
views: {
'tab-profile': {
templateUrl: 'templates/tab-profile.html',
controller: 'ProfileCtrl'
}
}
})
This is the tabs code. As showed in the video, the value is correctly updated:
<!-- Profile Tab -->
<ion-tab title="Profile" icon-off="ion-ios-person-outline" icon-on="ion-person" href="#/tab/profile/{{userId}}">
<ion-nav-view name="tab-profile"></ion-nav-view>
</ion-tab>
And this is my 'ProfileCtrl' code:
.controller('ProfileCtrl', function($http, $scope, $stateParams) {
$scope.$on('$ionicView.enter', function(e) {
console.log('$stateParams:');
console.log($stateParams);
});
I finally solved it. I finally managed to solve it.
I added this method:
$scope.goToUserProfile = function(){
$state.go('tab.profile', { userIdInUrl: AuthService.userId() });
};
And changed my tabs code to this:
<!-- Profile Tab -->
<ion-tab title="Profile" icon-off="ion-ios-person-outline" icon-on="ion-person" ng-click="goToUserProfile()">
<ion-nav-view name="tab-profile"></ion-nav-view>
</ion-tab>
Have a nice week!
I'm new to Ionic but it's been a long time since I wanted to try it. I'm just playing around so maybe I'm not getting the full concept.
I'm trying to do a simple application with three tabs at the bottom and a settings icon that will be there for all three tabs. When you click into that icon, supposedly the tabs should hide and show the settings screen.
Since I don't want the user to loose any content, all the views inherit from a global one:
angular.module('app', ['ionic', 'debug']).config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: "/app",
abstract: true,
controller: 'AppController',
templateUrl: "ui/modules/tabs/view.html"
})
.state('app.compose-text', {
url: '/text',
views: {
'compose-text': {
templateUrl: 'ui/modules/text-composer/view.html'
}
}
})
.state('app.compose-draw', {
url: '/draw',
views: {
'compose-draw': {
templateUrl: 'ui/modules/draw-composer/view.html'
}
}
})
.state('app.compose-photo', {
url: '/photo',
views: {
'compose-photo': {
templateUrl: 'ui/modules/photo-composer/view.html'
}
}
})
.state('app.settings', {
url: '/settings',
views: {
'settings': {
controller: 'ui/modules/settings/ctrl.js',
templateUrl: 'ui/modules/settings/view.html'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/text');
});
angular.module('app').run(function($rootScope) {
});
Then, tabs/view looks like this:
<ion-nav-view name="settings"></ion-nav-view>
<ion-tabs class="tabs-assertive tabs-icon-only">
<ion-tab title="Text" icon="icon ion-ios7-compose-outline" href="#/app/text">
<ion-nav-view name="compose-text"></ion-nav-view>
</ion-tab>
<ion-tab title="Draw" icon="icon ion-edit" href="#/app/draw">
<ion-nav-view name="compose-draw"></ion-nav-view>
</ion-tab>
<ion-tab title="Photo" icon="icon ion-ios7-camera-outline" href="#/app/photo">
<ion-nav-view name="compose-photo"></ion-nav-view>
</ion-tab>
</ion-tabs>
And one of the views:
<ion-view title="Example" class="slide-left-right">
<ion-nav-buttons side="left">
<a class="button button-icon button-clear ion-ios7-gear-outline" href="#/app/settings"></a>
</ion-nav-buttons>
<ion-content padding="true">
<h1>Text</h1>
</ion-content>
</ion-view>
First thing I wonder is: Is there any way to reuse those buttons between all views? Seems useless to keep defining them over and over.
But that's not the real thing™. When I click on Settings, something get injected into the ion-nav-view however it contains a lot of stuff (which is not on the template) and also, it doesn't hide the other view nor the tabs.
Some screenshot:
(source: ionicframework.com)
What should be the right approach for this?
This is my first time answering a question here so please bear with me.
To navigate to a view without the tab bar:
Remove the "app" prefix from the settings state, so it is no longer a child to the parent abstract state (app).
.state('settings', {
url: '/settings',
views: {
'settings': {
controller: 'ui/modules/settings/ctrl.js',
templateUrl: 'ui/modules/settings/view.html'
}
}
});
**If you add any states after this one, be sure to delete semicolon, whereas semicolon denotes the end.
THAT IS A BAND-AID SOLUTION.
The full solution to your problem is to start with an ionic project template. Fortunately they have a tabs option, which is a global tab bar.
Command-line:
ionic start appName tabs
That should give you a proper starting template with everything you need. It also has sample controllers.js, services.js, and app.js files so you can just build from there. It will also help you structure your project correctly to prevent unexpected data from injecting into your tag.
Source 1: http://ionicframework.com/getting-started/
Source 2: http://ionicframework.com/docs/api/directive/ionNavView/
**Bonus: There is also a neat trick in source 2 that shows you how to keep all templates inside your index.html file to speed up the app and simplify your workflow.
Goodluck.