I have a Ionic app based on the tabs template. The general navigation structure of my app is:
-- users (/users)
-- user (/users/[id])
-- todos (/todos)
-- todo (/users/[id])
-- settings (/settings)
There are some nested views there (user and todo). They appear in the same nav view, like so:
<ion-tabs class="tabs-icon-only tabs-color-assertive">
<ion-tab icon="ion-ios-pulse-strong" href="#/tab/users">
<ion-nav-view name="users-tab"></ion-nav-view>
</ion-tab>
<ion-tab icon="ion-ios-pulse-strong" href="#/tab/todos">
<ion-nav-view name="todos-tab"></ion-nav-view>
</ion-tab>
<ion-tab icon="ion-ios-pulse-strong" href="#/tab/settings">
<ion-nav-view name="settings-tab"></ion-nav-view>
</ion-tab>
</ion-tabs>
With states being defined thusly:
.state('tabs', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('users', {
url: '/users',
views: {
'users-tab': {
templateUrl: 'templates/tab-users.html',
controller: 'UsersCtrl'
}
}
})
.state('tabs.user', {
url: '/users/:userId',
views: {
'users-tab': {
templateUrl: 'templates/user-detail.html',
controller: 'UserCtrl'
}
}
})
.state('todos', {
url: '/todos',
views: {
'todos-tab': {
templateUrl: 'templates/tab-todos.html',
controller: 'TodosCtrl'
}
}
})
.state('tabs.todo', {
url: '/todos/:todoId',
views: {
'todos-tab': {
templateUrl: 'templates/todo-detail.html',
controller: 'TodoCtrl'
}
}
})
.state('tab.settings', {
url: '/settings',
views: {
'settings-tab': {
templateUrl: 'templates/tab-settings.html',
controller: 'SettingsCtrl'
}
}
})
In my index.html file, I have the following:
<ion-nav-bar class="bar-light">
<ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
I make use of the ion-nav-back-button to handle de master-detail views users and todos. This works completely automatically and Ionic handles this very well. Except for one case. When I refer to a detail view of a todo (e.g. /todos/3) from within another view (e.g. users/1), the back button does not appear, and there is no way to go back to the todos overview (/todos). A click on the tab button has no effect but going to /todos/3).
I guess this is expected behavior, but is there any way to show the back button anyway, or to make the tab button go to the todos view (/todos) at all times?
I found a solution. It's not ideal, but it works.
Instead of going directly to the detail state:
$state.go('tabs.todos', {
id: 1
});
I first go to the master state, and in the promise I go to the detail state:
$state.go('tabs.todos').then(function() {
setTimeout(function() {
$state.go('tabs.todos', {
id: 1
});
}, 100);
});
The timeout is not strictly necessary, but I've found that sometimes it fails without it.
Related
I am new to ionic, and what causes me most difficulty is the subject of navigation.
I have two tabs called "Dashboard" and "friends". I would like that when I click on the dashboard button, I can navigate to the subview that is called "subview_dash", but I do not want the tabs to be shown in this view. My problem is that I know how to navigate to this view, but I can not make the return button appear in "subview_dash".
How can I do it? I would appreciate it too.
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "tabs.html"
})
// Each tab has its own nav history stack:
.state('tab.dash', {
url: '/dash',
views: {
'tab-dash': {
templateUrl: 'tab-dash.html',
controller: 'DashCtrl'
}
}
})
.state('tab.friends', {
url: '/friends',
views: {
'tab-friends': {
templateUrl: 'tab-friends.html',
controller: 'DashCtrl'
}
}
})
.state('subview_dash', {
url: '/subview_dash',
templateUrl: 'tab-subview_dash.html',
controller: 'DashCtrl'
})
This is my code:
http://plnkr.co/edit/Az3w9O8rkr7fJw4unIDz?p=preview
You use this code in tab-subview_dash.html
<ion-view title="subview_dash">
<ion-nav-buttons side="left">
<button class="button button-clear ion-arrow-left-c" ng-click="backButton()"></button>
</ion-nav-buttons>
<ion-content class="has-header">
friends
</ion-content>
</ion-view>
and write your function for backButton() give path where you want to redirect
I'm building a mobile app with ionic, I'm facing a strange problem ..
If I reload the page ( F5 ) from, let say "/tabs/connected/channel/edit" I'm always redirected to "/tabs/home" ( after the state resolving ).
PS : The resolve phase is correclty executed and I never reject it. And then on promise resolving I'm always redirected to /tabs/home.
Here is my config block :
.config(function($stateProvider, $urlRouterProvider) {
var userResolve = function(user, $q, $auth) {
if (!$auth.isAuthenticated()) {
return $q.resolve();
}
if (user.loaded) {
return $q.resolve();
}
return user.blockingRefresh();
};
// 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('tabs', {
url: '/tabs',
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('tabs.home', {
url: '/home',
views: {
'home-tab': {
templateUrl: 'templates/home.html',
controller: ''
}
}
})
.state('tabs.account', {
url: '/account',
views: {
'account-tab': {
templateUrl: 'templates/account/account.html',
controller: 'AccountController'
}
},
resolve: {
userData: userResolve
}
})
.state('tabs.login', {
url: '/account/login',
views: {
'account-tab': {
templateUrl: 'templates/account/login.html',
controller: 'AccountController'
}
}
})
.state('tabs.register', {
url: '/account/register',
views: {
'account-tab': {
templateUrl: 'templates/account/register.html',
controller: 'RegisterController'
}
}
})
.state('tabs.connected', {
url: '/connected',
abstract: true,
views: {
'account-tab': {
templateUrl: "templates/connected.html"
}
},
resolve: {
userData: userResolve
}
})
.state('tabs.connected.channel-create', {
url: '/channel/create',
templateUrl: 'templates/channel/create.html',
controller: 'CreateChannelController'
})
.state('tabs.connected.channel-edit', {
url: '/channel/edit',
templateUrl: 'templates/channel/edit.html',
controller: 'EditChannelController'
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tabs/account');
})
Here is tabs.html :
<ion-tabs class="tabs-assertive tabs-icon-top">
<ion-tab title="Home" ui-sref="tabs.home" icon-on="ion-ios-filing" icon-off="ion-ios-filing-outline">
<ion-nav-view name="home-tab"></ion-nav-view>
</ion-tab>
<ion-tab title="Account" ui-sref="tabs.account" icon-on="ion-ios-gear" icon-off="ion-ios-gear-outline">
<ion-nav-view name="account-tab"></ion-nav-view>
</ion-tab>
I must precise that I never use $state.go('/tabs/home') I'm my code at all. I'm sure of that.
My goal is to stay on the same route even if I reload the app. ( This problem does not occurs on some state and I don't know why because they doesn't do anything different than the problematic ones .. )
Thank you !
I also got this type of error in Angular Ui-Router.
Below solution is work for me.
Just change it too
.state('tabs.connected.channelcreate', {
url: '/channelcreate',
templateUrl: 'templates/channel/create.html',
controller: 'CreateChannelController'
})
url should be
"/tabs/connected/channeledit"
And it will work.
Ideally, all 3 methods ought to work.
This codepen below shows all 3 methods well.
Correct and working CodePen Demo app
Currently, neither of the 3 methods work; the navbar just dissappears upon clicking the button (shows empty nav bar) while the core page remains the same main page.
Im not sure if its an code problem, ionic issue or just simply I should not transit to a new page from a navbar. The last one is too illogical to accept though.
Would any kind souls know where the issue lie and help me please?
My core content code in index.html
<body animation="slide-left-right-ios7">
<ion-nav-bar class="bar-light nav-title-slide-ios7"></ion-nav-bar>
<ion-nav-view></ion-nav-view>
The button html I have (Note all 3 versions were tested seperately)
<ion-view ng-controller="NavCtrl">
<ion-nav-buttons side="left">
<button class="button button-icon ion-compose" ng-click="create('tab.newpost')"></button>
<button class="button button-icon ion-compose" ui-sref="tab.newpost"></button>
<button class="button button-icon ion-compose" href="/tab/newpost"></button>
</ion-nav-buttons>
<ion-content class>
<!-- Rest of the content body here -->
</ion-content>
</ion-view>
Code in nav.js mainly for the state.create method
app.controller('NavCtrl', function ($scope, $location, $state, Post, Auth) {
$scope.post = {url: 'http://', title: ''};
$scope.create = function(stateName) {
/* $location.path('/tab/newpost'); */
$state.go(stateName); /* tried swapping stateName with 'tab.newpost' and func() */
};
});
Code for app.js (Route file)
var app = angular.module('MyApp', ['ionic','firebase']);
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('tab.posts', {
url: '/posts',
views: {
'tab-posts': {
templateUrl: 'templates/tab-posts.html',
controller: 'PostsCtrl'
}
}
})
.state('tab.newpost', {
url: '/newpost',
views: {
'tab-newpost':{
templateUrl: 'templates/tab-newpost.html',
controller: 'NewCtrl'
}
}
});
/* + other states .... */
$urlRouterProvider.otherwise('/auth/login');
});
First method you used according to the your code look like this
ng-click="create('tab/newpost')"
It should be
ng-click="create('tab.newpost')"
i think you need to modify states name so you can navigate between them
var app = angular.module('MyApp', ['ionic','firebase']);
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('tab.posts', {
url: '/posts',
views: {
'tab-posts': {
templateUrl: 'templates/tab-posts.html',
controller: 'PostsCtrl'
}
}
})
.state('tab.newpost', {
url: '/newpost',
views: {
'tab-posts':{ /* the same name of the above state */
templateUrl: 'templates/tab-newpost.html',
controller: 'NewCtrl'
}
}
});
/* + other states .... */
$urlRouterProvider.otherwise('/auth/login');
});
i'm new in ionic ( just a little less in angularjs ) .
i'm trying to do a simple switch between two views:
HTML
<body ng-app="starter" animation="slide-left-right-ios7">
<!--
The nav bar that will be updated as we navigate between views.
-->
<ion-nav-bar class="bar-stable nav-title-slide-ios7">
<ion-nav-back-button class="button-icon icon ion-ios7-arrow-back">
Back
</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view name="intro"></ion-nav-view>
<ion-nav-view name="login"></ion-nav-view>
<ion-nav-view name="home"></ion-nav-view>
<ion-nav-view name="pizze"></ion-nav-view>
<ion-nav-view name="sponsor"></ion-nav-view>
<ion-nav-view name="scontrino"></ion-nav-view>
</body>
APP.js
.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
.state('intro', {
url: '/intro',
views: {
'intro': {
templateUrl: 'templates/intro.html',
controller: 'IntroCtrl'
}
}
})
.state('login', {
url: '/login',
views: {
'login': {
templateUrl: 'templates/login.html',
controller: 'LoginCtrl'
}
}
})
$urlRouterProvider.otherwise('/intro');
});
Controllers.js
angular.module('starter.controllers', [])
.controller('IntroCtrl', function($scope,$location) {
$location.url("/login");
})
.controller('LoginCtrl', function($scope,$location) {
})
Intro is shown correctly but when it tries to change location to "login.html" it says:
TypeError: Cannot read property 'querySelectorAll' of undefined
at cancelChildAnimations (http://localhost:8000/www/lib/ionic/js/ionic.bundle.js:30611:21)
at Object.leave (http://localhost:8000/www/lib/ionic/js/ionic.bundle.js:30176:11)
at Object.leave (http://localhost:8000/www/lib/ionic/js/ionic.bundle.js:38411:24)
at updateView (http://localhost:8000/www/lib/ionic/js/ionic.bundle.js:41540:31)
at eventHook (http://localhost:8000/www/lib/ionic/js/ionic.bundle.js:41501:17)
at Scope.$broadcast (http://localhost:8000/www/lib/ionic/js/ionic.bundle.js:21190:28)
at $state.transition.resolved.then.$state.transition (http://localhost:8000/www/lib/ionic/js/ionic.bundle.js:33975:22)
at wrappedCallback (http://localhost:8000/www/lib/ionic/js/ionic.bundle.js:19894:81)
at http://localhost:8000/www/lib/ionic/js/ionic.bundle.js:19980:26
at Scope.$eval (http://localhost:8000/www/lib/ionic/js/ionic.bundle.js:20906:28)
What could be the problem???
Thanks!
Try this
angular.module('starter.controllers', [])
.controller('IntroCtrl', function($scope,$state) {
$state.transitionTo("login");
})
.controller('LoginCtrl', function($scope,$location) {
})
You are using the view names wrong.
In a state, the view's name
views: {
'_name_': {
}
is used for different navigation histories for different views.
Say you have two tabs, home and pizza, and you want both to have several pages, then the view name comes in handy.
For your example it is important to know, how you want the views to be used.
I set up an example for you, making the views accessible in tabs.
See here for that example: http://plnkr.co/edit/Yd5ehQd0wnwlPzP0KYnp?p=preview
This is the situation:
I am using Angular Js into Ionic framework to make a mobile app.
I start up the project using the tabs boilerplate. I have three tabs right now: Login - Friends - Map.
I want to add an additional view, named 'member area', that is accessible after the login pass succesfully, but i am not able to do.
In the initial setup of the ionic tabs project, each view is defined as state.
This is the code:
angular.module('starter', ['ionic','AngularGM', 'starter.controllers', 'starter.services'])
.run(function($ionicPlatform){
$ionicPlatform.ready(function(){
if(window.StatusBar){
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.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.login', {
url: '/login',
views: {
'tab-login': {
templateUrl: 'templates/tab-login.html',
controller: 'LoginController'
}
}
})
.state('tab.friends', {
url: '/friends',
views: {
'tab-friends': {
templateUrl: 'templates/tab-friends.html',
controller: 'FriendsCtrl'
}
}
})
.state('tab.friend-detail', {
url: '/friend/:friendId',
views: {
'tab-friends': {
templateUrl: 'templates/friend-detail.html',
controller: 'FriendDetailCtrl'
}
}
})
.state('tab.map', {
url: '/map',
views: {
'tab-map': {
templateUrl: 'templates/tab-map.html',
controller: 'mapController'
}
}
});
$urlRouterProvider
// if none of the above states are matched, use this as the fallback
.otherwise('/tab/login');
});
This is what have tried to do:
1. Adding memberArea as .when
$urlRouterProvider
.when('/memberArea', {
templateUrl: 'main/memberArea',
controller: 'memberAreaController'
})
// if none of the above states are matched, use this as the fallback
.otherwise('/tab/login');
});
But in doing this the app crash with this error:
Uncaught Error: [$injector:modulerr] Failed to instantiate module starter due to:
Error: invalid 'handler' in when()
2. Adding memberArea as a state:
.state('memberArea', {
url: '/memberArea',
views: {
'memberArea': {
templateUrl: 'templates/memberArea.html',
controller: 'memberAreaController'
}
}
});
But is not working, accessing the url #/memberArea gives a blank page (no error in console)
3. Add memberArea as a tab:
.state('tab.memberArea', {
url: '/memberArea',
views: {
'tab-memberArea': {
templateUrl: 'templates/memberArea.html',
controller: 'memberAreaController'
}
}
});
and add the tab itself:
<!-- memberArea -->
<ion-tab title="memberArea" icon="icon ion-home" href="#/tab/memberArea">
<ion-nav-view name="tab-memberArea"></ion-nav-view>
</ion-tab>
In this way is working.. but is a tab and shouldn't be there the view.
If i remove this HTML for the tab menu, then the view is not accessible anymore from the URL address.
This is the question:
How can i properly define an additional view in Angular js + Ionic (with tabs) ?
Thank you very much!
If you don't want to handle the MemberArea as a tab, you should use the following syntax:
.state('memberArea', {
url: '/memberArea',
templateUrl: 'templates/memberArea.html'
}
);
If you place a . before the item in the states, you are saying it should inherit the parent.
For example tab.member will mean member inherits from tab.
Also if you use a stateProvider, you can no longer write the format as a urlProvider as per your example 1. It would have to be like your last line, otherwise. ....etc.
I would think a controller is still required, regardless if its on tab or not. (Correct me if Im wrong).
If u want to properly define an additional view not as a tab, then you should follow option 2, adding memberArea as a state:
.state('memberArea', {
url: '/memberArea',
templateUrl: 'templates/memberArea.html'
}
);
Use ui-sref='memberArea' instead of href in the element, on clicking of which you will show MemberArea.
And just check if this view location is available to the app.