• No results found

Adding ionNavView for each tab

In document Ionic in Action (Page 121-126)

Tabs, advanced lists, and form components

5.3 Adding ionNavView for each tab

Your tabs are empty, and you want to use additional ionNavView components to load your components. This will allow each of the tabs to maintain its own navigational history. It allows you to use a back button that’s only for a given tab instead of the

Listing 5.3 tabs template (www/views/tabs/tabs.html)

Declares ionTabs component to wrap all tabs and gives it a class to modify title and icon display

Declares tabs with titles and icons for active and inactive states

whole app. In figure 5.3 you can see how the user experience would flow with each tab having its own navigational history. If you’re following along using Git, you can check out the code for this step:

$ git checkout –f step3

Tab 1

View 1 1. Start on

tab 1, view 1

2. Go to tab 1,

view 2 3. Go to tab 2

4. Return to Tab 1, view 2

Tab 2 Tab 3

View 2

Figure 5.3 Flow through tabs with individual navigational histories

Tabs don’t require individual views

Tabs can contain any content you wish to put inside. Essentially a tabbed interface is really just one large view that has only one tab displayed at once, with the other tabs in a hidden state. It would be similar to having several pages of paper stacked on top of one another, and at any time you can move a lower page to the top so it’s visible.

The technique of using the ionNavView element inside of each tab gives you one major benefit. Each tab is able to have its own history. So instead of a stack of papers, it’s now more like a stack of books where the topmost book is open to a par-ticular page, and if you switched books you’d bookmark that page and return to the exact same spot later.

You’ll start by adding the ionNavView components into your tabs. You’ll have to give each one a name so they can be identified later. You can only have one ionNavView that’s not named in your Ionic app, and the unnamed ionNavView is always the default view. Each tab will also be given a ui-sref attribute that will turn the tab icons into buttons to navigate between tabs. This section won’t look drastically different when you preview it, but as you see in figure 5.4, it will now show a title in the header bar for the active tab.

Open the www/views/tabs/tabs.html template file and update to what you see in the following listing. Updates to this template are in bold.

<ion-tabs class="tabs-icon-top tabs-positive">

<ion-tab title="Rates" icon-on="ion-social-bitcoin" icon-off=

"ion-social-bitcoin-outline" ui-sref="tabs.rates">

<ion-nav-view name="rates-tab"></ion-nav-view>

</ion-tab>

<ion-tab title="History" icon-on="ion-ios-analytics" icon-off=

"ion-ios-analytics-outline" ui-sref="tabs.history">

<ion-nav-view name="history-tab"></ion-nav-view>

</ion-tab>

<ion-tab title="Currencies" icon-on="ion-ios-cog" icon-off=

"ion-ios-cog-outline" ui-sref="tabs.currencies">

<ion-nav-view name="currencies-tab"></ion-nav-view>

</ion-tab>

</ion-tabs>

This adds three new ionNavView components with a different name. The ui-sref attributes act like a normal href attribute to link to a particular state based on the

Listing 5.4 tabs template with individual views (www/views/tabs/tabs.html) (continued)

Essentially it boils down to how you use the tabs. I’d classify two primary use cases:

tabs for providing navigation, and tabs for fitting more content in a single view.

When using tabs for navigation, adding individual views is useful. This chapter exam-ple will demonstrate this use case.

Using tabs to fit more content into a single view wouldn’t benefit from individual views. For example, you could use tabs in a weather app for displaying the current conditions. Because the current condition information is likely loaded all at once from an API, and the information is logically connected, you’d probably use tabs to sepa-rate the information into simpler chunks. Imagine there were three tabs: current con-ditions, weather map, and 10-day forecast.

My general recommendation is that if the content of the tabs could be logically placed into one view and controller, then you probably don’t want to use individual ionNav-View components.

Adds ui-sref to change view on tab selection

Defines and names ionNavView for each tab

name, so instead of having a URL, you have a state name. Even though only one of these three views will be visible, all three will be part of the same parent tabs view.

Now you need to add routes to the config() that will support these new views. Ui-router has a feature called nested states that allows you to declare states with a hierar-chy. In this case, the tabs route that displays the tabs is like the root state, and each tab is a child state underneath it. This is helpful when you need to logically organize states and helps the Ionic navigation components understand your app’s navigational struc-ture. You need to update the app config() with the new states and modify the tabs state as well. The following listing has the updated states configuration with updates bolded.

templateUrl: 'views/tabs/tabs.html' })

.state('tabs.rates', { url: '/rates',

Listing 5.5 App config() with tab child states (www/js/app.js) Navbar

Each tab has its own ionNavView, and the tabs container is the parent. Each tab can have its own navigation history because it’s a unique ionNavView.

Hierarchy of ionNavView elements

Figure 5.4 Tabs with individual views, showing the title as you change tabs

Updates tabs state to be abstract because you always want to use a child

B

Declares tabs.rates state using dot notation for parent.child relationship

C

Declares URL for route; it’s a child route, so it appends this to URL of parent

D

views: {

.state('tabs.currencies', { url: '/currencies', views: {

'currencies-tab': {

templateUrl: 'views/currencies/currencies.html' }

} });

$urlRouterProvider.otherwise('/tabs/rates');

})

There are a few things going on here that are new in the states configuration. The tabs route

B

now has the abstract: true property set, which makes it possible to declare it as a parent but doesn’t allow it to be an active state.

The rates state has the name declared with tabs.rates

C

. This is to indicate the parent and child relationship they have. The URL is also declared here

D

, but take note that when you have a parent-child relationship, the URL is actually appended to the end of the parent URL. The rates view URL is actually found at /tabs/rates and not just /rates. Lastly, subviews of the state

E

are declared. The view must be named the same as the name you gave to the ionNavView earlier, in this case rates-tab. The app now knows that when the rates tab is active, it should inject the specified template into that view. Later you’ll declare other view properties such as controllers.

Lastly, the code updates the default route from /tabs to /tabs/rates

F

. This is because in the tabs you always want to be on one of the tabs, so the tabs container state is abstract. If you attempt to go to the tabs route (/tabs), it will now redirect you to the default rates view.

The last task in this section is to add the basic templates for each of the three tabs.

You’ve already declared them in your states using the templateUrl property in the view. The next three listings contain simple templates with a view and title for each tab.

<ion-view view-title="Current Rates">

<ion-content>

</ion-content>

</ion-view>

Listing 5.6 Rates tab basic template (www/views/rates/rates.html)

Rates view targets view with this name and passes a template for that view

<ion-view view-title="Hourly Average Price">

These templates are blank for the moment, but you’ll update each one individually in the following sections. If you preview the app in your browser, you’ll be able to see the title changing as you change tabs on the bottom. This finishes what you need to do with tabs, so let’s get to work on creating the first tab and showing the current Bit-coin rates.

In document Ionic in Action (Page 121-126)