Uso de tabs en Ionic

Alexander A. Ramírez M.

Otro patrón de navegación muy frecuente en las aplicaciones es el uso de tabs. En ionic esto se logra mediante el uso de la directiva ion-tabs.

La jerarquía de estos elementos es la siguiente:

.
+-- ion-nav-bar
|   |
|   +-- ion-nav-back-button
|   |
|   +-- ion-nav-buttons
|   |
|   +-- ion-nav-title
|
+-- ion-nav-view
    |
    +-- ion-tabs
        |
        +-- ion-tab
            |
            +-- ion-nav-view (named)
                |
                +-- ion-view

Le estructura de un ion-view permite cambiar el comportamiento definido por el padre para la barra de navegación, el título, los botones y el uso de headers o footers.

.
+-- ion-view (class="has-subheader has-subfooter")
    |
    +-- ion-nav-buttons
    |
    +-- ion-nav-title
    |
    +-- ion-header-bar
    |
    +-- ion-footer-bar
    |
    +-- div class="sub-header"
    |
    +-- div class="sub-footer"

Vamos a seguir el mismo ejemplo que hicimos con ion-side-menus pero con ion-tabs.

Uno de los aspectos más resaltantes es que en la definición de los ion-tabs cada ion-tab contiene una vista de navegación ion-nav-view con un nombre específico. Esto implica que cada vista de navegación mantiene su propio estado. Es decir que la historia de navegación es distinta, lo cual implica que cada vez que cambiamos de tab lo vamos a encontrar en el estado que lo dejamos y podemos navegar desde ese punto a las vistas previas que hayamos navegado. Esa es una de las ventajas fundamentales de los tabs.

Ingrese a play.ionic.io para obtener el código para iniciar el tutorial y haga FORK. No olvide hacer FORK.

El objetivo es:

  • Crear una aplicación con múltiples tabs (o vistas) y con navegación a través de los mismos.
  • Crear la plantilla inicial con los tabs y el resto de las vistas.
  • Definir los estados de la aplicación.
  • Definir los controladores.
  • Hacer un pantalla con parámetros que se envían a través de ui-router.

Primero vamos a definir la vista de navegación que va a contener toda la aplicación.

<body ng-app="app">
<ion-nav-view>
</ion-nav-view>

Ahora vamos a crear la plantilla donde definimos los tabs con la directiva ion-tabs.

<script id="templates/tabs.html" type="text/ng-template">
  <ion-tabs class="tabs-assertive tabs-icon-top">

  </ion-tabs>
</script>

Ahora vamos a definir cada tab con la directiva ion-tab.

<script id="templates/tabs.html" type="text/ng-template">
  <ion-tabs class="tabs-assertive tabs-icon-top">
    <ion-tab title="Presentación" href="#/tabs/presenta" icon="ion-monitor">

    </ion-tab>
    <ion-tab title="Empleados" href="#/tabs/empleados" icon="ion-person-stalker">

    </ion-tab>
    <ion-tab title="Contacto" href="#/tabs/contacto" icon="ion-location">

    </ion-tab>
  </ion-tabs>
</script>

Ahora en cada tab hay que definir las vistas de navegación mediante la directiva ion-nav-view y donde se mantendrá la historia de navegación.

<script id="templates/tabs.html" type="text/ng-template">
  <ion-tabs class="tabs-assertive tabs-icon-top">
    <ion-tab title="Presentación" href="#/tabs/presenta" icon="ion-monitor">
      <ion-nav-view name="presenta-tabs">
      </ion-nav-view>
    </ion-tab>
    <ion-tab title="Empleados" href="#/tabs/empleados" icon="ion-person-stalker">
      <ion-nav-view name="empleados-tabs">
      </ion-nav-view>
    </ion-tab>
    <ion-tab title="Contacto" href="#/tabs/contacto" icon="ion-location">
      <ion-nav-view name="contacto-tabs">
      </ion-nav-view>
    </ion-tab>
  </ion-tabs>
</script>

Ya tenemos la plantilla principal donde definimos la navegación. Fíjese que cada tab cuenta con un href que direcciona a una ruta correspondiente a cada tab. Dicha ruta deberá definirse en nuestra configuración en el JS.

Vamos a definir las plantillas correspondientes a cada estado.

<script id="templates/presenta.html" type="text/ng-template">
  <ion-view view-title="Presentación">
    <ion-content>
      <h1>Aquí presentamos</h1>
    </ion-content>
  </ion-view>
</script>

<script id="templates/empleados.html" type="text/ng-template">
  <ion-view view-title="Empleados">
    <ion-content>
      <ion-list>
        <ion-item>
          Empleado del mes
        </ion-item>
        <ion-item>
          Otro empleado
        </ion-item>
      </ion-list>
    </ion-content>
  </ion-view>
</script>

<script id="templates/contacto.html" type="text/ng-template">
  <ion-view view-title="Contacto">
    <ion-content>
      <h1>Contacto</h1>
    </ion-content>
  </ion-view>
</script>

Ahora vamos a definir nuestros estados y rutas para ver la aplicación funcionando con los tabs definidos y los cambios de estado.

.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('tabs', {
      url: "/tabs",
      abstract: true,
      templateUrl: "templates/tabs.html",
      controller: 'appController'
    })
    .state('tabs.presenta', {
      url: "/presenta",
      views: {
        'presenta-tabs': {
          templateUrl: "templates/presenta.html",
          controller: "presentaController"
        }
      }
    })
    .state('tabs.empleados', {
      url: "/empleados",
      views: {
        'empleados-tabs': {
          templateUrl: "templates/empleados.html",
          controller: "empleadosController"
        }
      }
    })
    .state('tabs.contacto', {
      url: "/contacto",
      views: {
        'contacto-tabs': {
          templateUrl: "templates/contacto.html",
          controller: 'contactoController'
        }
      }
    });
    
    $urlRouterProvider.otherwise('/tabs/presenta');
});

Definamos los controladores respectivos de acuerdo a la configuración que acabamos de hacer.

angular.module('app', ['ionic'])

.controller('appController', function($scope) {

})  

.controller('presentaController', function($scope) {

})

.controller('empleadosController', function($scope) {

})

.controller('contactoController', function($scope) {

})

Finalmente vamos a definir una plantilla de detalles de un empleado que recibe parámetros de la plantilla empleados. Primero debemos indicar al estado que vamos a navegar con ui-sref que provee ui-router y enviamos un parámetro que va a recibir la pantalla de detalles de empleado.

<script id="templates/empleados.html" type="text/ng-template">
  <ion-view view-title="Empleados">
    <ion-content>
      <ion-list>
        <ion-item ui-sref="tabs.empleado({id:1})">
          Empleado del mes
        </ion-item>
        <ion-item ui-sref="tabs.empleado({id:2})">
          Otro empleado
        </ion-item>
      </ion-list>
    </ion-content>
  </ion-view>
</script>

<script id="templates/empleado.html" type="text/ng-template">
  <ion-view view-title="Empleado">
    <ion-content>
      <h1>Empleado </h1>
    </ion-content>
  </ion-view>
</script>

El parámetro no llega hasta que se defina en el controlador correspondiente. Debemos inyectar $stateParams y rescatar el parámetro para crearlo en el modelo ($scope).

.controller('empleadoController', function($scope, $stateParams) {
  $scope.id = $stateParams.id;
})

Puede consultar el resultado del tutorial.

Les dejo un ejemplo que utiliza tabs y side-menu.