Animating onto, and keeping history for a tabbed page - angularjs

I'm just starting out with Ionic, and have run into a bit of a confusing problem; I have a couple of pages set up (Properties, Test and Xyzzy) set up as follows in the router:
$stateProvider
.state( 'properties', {
url: '/properties',
templateUrl: 'templates/properties.html',
controller: 'PropertiesController'
} )
.state( 'test', {
url: '/test',
abstract: true,
templateUrl: 'templates/test.html',
controller: 'TestController'
} )
.state( 'test.one', {
url: '/one',
views: {
'one-tab': {
templateUrl: 'templates/test-one.html',
controller: 'TestController'
}
}
} )
.state( 'test.two', {
url: '/two',
views: {
'two-tab': {
templateUrl: 'templates/test-two.html',
controller: 'TestController'
}
}
} )
.state( 'xyzzy', {
url: '/xyzzy',
templateUrl: 'templates/xyzzy.html',
controller: 'XyzzyController'
} );
Essentially there are two plain-and-simple pages (Properties and Xyzzy) and one page with tabs (Test). The templates for each page are very simple, and look like this - Properties, Xyzzy and Test
Enough explaining, here's the problem: as you can see, the Xyzzy page has detected that I've navigated to it from the Properties page and gives me a nice back button. It doesn't show up if I go to the Test page though (with the tabs). The code for that is this:
<ion-nav-bar class="bar-positive">
<ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>
Also, when I navigate between Properties and Xyzzy, the page slides left/right in a nice little animation which looks clean. However, when I go into the Test page, there's no transition at all, nor is there when I come out of it.
I've spent a couple of hours looking around Google but can't find anything relevant to transitions in/out of tabbed pages. Any ideas?
Update: Here's the code the views are being built off (in index.html):
<body ng-app="app">
<ion-nav-bar class="bar-positive">
<ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view animation="slide-left-right"></ion-nav-view>
</body>

for the transition you can use
<ion-nav-view name="main" animation="slide-left-right"></ion-nav-view>
for your pages

Related

Navigate from one tab to a nested view of another tab

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

Angular ui-router subview issues

I've been working with Angular for a year or 2 now, but this is my first project using ui-router. I'm running into a few issues with views and sub-views. The app is a standard left-side menu bar, with the views on the right changing depending on what's clicked in the menu bar.
On index.html
<body>
<div ui-view></div>
</body>
In the config.js file, which defines the routes
.state("dashboard", {
url: "/dashboard",
templateUrl: "components/dashboard/dashboard.html",
data: {
pageTitle: "Dashboard",
requiresLogin: false
}
})
.state("dashboard.welcome", {
url: "/welcome",
templateUrl: "components/welcome/welcome.html",
data: {
pageTitle: "Welcome",
requiresLogin: false
}
})
In the dashboard.html file
<div class="dashboard">
<div class="container-fluid">
<div class="row">
<div class="col-xs-12 col-md-8">
<div ui-view>
The /dashboard path loads correctly, and will load the left-side navigation bar with a blank right side. But changing the state to dashboard.welcome (/welcome) will not load the welcome.html template.
Whenever working with ui-router you need to understand that the concept of states is different from routes. When you define a sub-state, its defined relative to its parent state. In your scenario dashboard.welcome is defined as a child state of dashboard. The routes to substate is relative to the parent and is {parent url}/{child url}. Hence you should use either of the below 2 to route to that state:
Using $state.go change the state by specifying state name
$state.go('dashboard.welcome');
Using $location.path change the route by specifying url
$location.path('/dashboard/welcome');
It sounds like you want links to /welcome to be for state dashboard.welcome. Here is a plunker showing how this can be done. I show two sets of dashboard and welcome states. The first set of states (dashboard & welcome) shows that /dashboard/welcome will bring you to the dashboard.welcome state.
The second set (dashboard2 & welcome2) shows that /welcome will go to state dashboard2.welcome2. I believe this is what you were looking for.
If you hover over the links you can see where they will take you.
https://plnkr.co/edit/AVKPFa?p=info
Nested routes in ui-router get nested urls. I would however recommend using named-views for this kind of structure. You can find more info about it here:
https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
The gist of it is: you can specify a named component (ui-view) for your left menu navigation and another one for content, which gives you much more control down the line, because named components can be overwritten in child states or they can keep the default template, depending on your needs.
Example:
.state('root', {
url: '',
abstract: true,
views: {
'header': {
templateUrl: 'templates/partials/header.html',
controller: 'headerCtrl'
},
'logo': {
templateUrl: 'templates/partials/logoView.html'
},
'footer':{
templateUrl: 'templates/partials/footer.html',
controller: 'footerCtrl'
}
}
})
.state('root.login', {
url: '/login',
views: {
'header#': {
template: ''
},
'container#': {
templateUrl: 'templates/login.html',
controller: 'loginController'
}
}
})
.state('root.report', {
url: '/report',
views: {
'container#': {
templateUrl: 'templates/eu_dashboard.html',
controller: 'reportController'
}
}
})
And in your index.html:
<div ui-view="logo"></div>
<div ui-view="header"></div>
<div id="mainView" ui-view="container"></div>
<div ui-view="footer"></div>

Multiple layouts with UI-Router

I have a project for which I need 2 layouts. One which is basically 1 column (kind of as a landing page) and one which has a menu at the top, and is basically the same 1 column layout.
I've set up 2 layout HTMLs, which I'm using in my states, but the problem is that every time I switch from one state to the other, the whole HTML in the top-most ui-view (the one in the body) is changed.
Here's my setup:
Routes
.state('root', {
url: '',
abstract: true,
templateUrl: 'app/layouts/logged-in.html'
})
.state('root.homepage', {
url: '/',
templateUrl: 'app/main/main.html',
controller: 'MainController',
controllerAs: 'main'
})
.state('candidate', {
url: '/candidate',
abstract: true,
templateUrl: 'app/layouts/logged-in.html'
})
.state('candidate.profile', {
url: '/profile',
templateUrl: 'app/candidate/profile.html',
controller: 'CandidateProfileController',
controllerAs: 'profile'
})
index.html
<body>
<div ui-view></div>
</body>
logged-in.html
<div>
<my-navbar></my-navbar>
</div>
<div ui-view></div>
logged-out.html
<div ui-view></div>
The problem is that when switching between root.homepage and candidate.profile, my-navbar gets removed and then re-appended, which the user can briefly see (until the new HTML loads). I'd understand if one of the states would have the logged-out.html layout and the other the logged-in.html layout, but we're talking about the same file, and I'm looking to update only the ui-view from inside logged-in.html file.
Might be better to create an abstract state for the logged-in (including the navbar) and then inside introduce div for placing named view mainContent. And configure all your states to extend logged-in state, with defining views:{'mainContent': {controller:... , templateUrl: ... } }

Ionic back button not working even though ionicHistory back view exists

My ionic back button doesn't do anything when it is being clicked even though, when I print out the version history, it shows that there is a back view. Also for some reason $ionicHistory.enabledBack() is returning false, even though the back view exists and the back view and current view have the same id. Does anyone know how to fix the problem?
Here's a snapshot of the console.
Use ui-router nested views to create states that will replace an ion-nav-view tag in the HTML.
Use ion-view, not ion-nav-view, inside the template html for each nested view.
Example:
Parent (Nav) View HTML:
<ion-nav-view name="navView"></ion-nav-view>
Nested View Level 1 HTML:
<ion-view view-title="Nested View Level 1">
<ion-content></ion-content>
</ion-view>
Nested View Level 2 HTML:
<ion-view view-title="Nested View Level 2">
<ion-content></ion-content>
</ion-view>
ui-router:
$stateProvider
.state('app.navView', {
url: '/nav-view',
views: {
'menuContent': {
templateUrl: 'app/navView.html',
controller: 'NavViewCtrl as vm'
}
}
})
.state('app.nestedViewL1', {
url: '/nested-view-L1',
views: {
'navView': {
templateUrl: 'app/nestedViewL1.html',
controller: 'NestedView1CtrL1 as vm'
}
}
})
.state('app.nestedViewL2', {
url: '/nested-view-L2',
views: {
'navView': {
templateUrl: 'app/nestedViewL2.html',
controller: 'NestedViewL2Ctrl as vm'
}
}
})

Creating views outside ion-tabs on Ionic Framework

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.

Resources