Framework Ionic Javascript. Ejemplo de aplicación y migración de Ionic 3 a Ionic 5

El objetivo de este articulo es reutilizar el código generado hace 3 años en Ionic 3 (https://github .com/al118345/IONIC-3-example-APP) y adaptarlo parcialmente a Ionic 5 (https://github.com/al118345/ionic_example_login)

Realmente me encontré que el proyecto implementado en Ionic 3 no funciona con la versión de Node.js que tengo instalado en mi entorno de desarrollo actual. Por lo tanto, he decidido crear dos proyectos, por una parte código que utilice en la versión 3 y por otra el código equivalente en ionic 5.

Para ello crearemos un proyecto nuevo en Ionic 5 y copiaremos y modificaremos ciertas partes del código.

Creación de la aplicación

  • El proyecto Ionic 3 (https://github .com/al118345/IONIC-3-example-APP) ha sido creado una aplicación mediante la plantilla básica “tabs” de Ionic Framework y hemos personalizado la pantalla de inicio de la siguiente manera:

    Para realizar esta tarea primero tenemos que instalar Ionic siguiendo las instrucciones del material de referencia:
    • Instalar o comprobar que tenemos instalado nodeJS en su versión 4
    • Instalar cordova e ionic como npm desde línea de comandos mediante:
           
                 npm install -g cordova ionic
                 
          
    • Instalar la aplicación con Ionic View 3
           
                 npm install @ionic/cloud-angular --save
                 
          

      Para realizar la migración a la versión 5 de Ionic View 3

           
                 npm uninstall ionic-angular
                 npm install @ionic/angular
                 
          
    • Entonces podemos crear una nueva app donde importamos el proyecto antiguo.
           
                 ionic start myApp blank
                 
          

  • El proyecto tenía como objetivo realizar un login con las siguientes credenciales:
    • Usuario : demo
    • Contraseña : demo

    Ionic 3

    A partir de esta idea, en su momento ejecuté los siguientes comandos desde la terminal
         
               ionic g provider authoService
               ionic g provider login
               ionic g provider logout
               
        
    Una vez creado las nuevas páginas, he generado el modelo de datos de los usuarios(models/user.ts)
         
               export class User {
            name: string;
            email: string;
    
            constructor(name: string, email: string) {
                   this.name = name;
                   this.email = email;
                 }
               }
               
        
    Con el modelo creado, he modificado el servicio para generar el login. Esta modificación está almacenada en el fichero providers/autho-service/autho-service.ts y el método más importante es el login, mostrado a continuación:
         
              login(credentials): Observable<boolean> {
            if (credentials.email === null || credentials.password === null) {
                       return Observable.throw("Please insert credentials");
                    } else {
                        this.logueado = false;
                         return Observable.create(observer => {
            //nos comunicamos con el servicio web de login
            //y con el resultado  que nos proporcione redirigimos al
            //hombe o nos quedamos en el login
            this.comunicaciones.login_Web( credentials.email, credentials.password).subscribe(result => {
                                 if (result === true) {
            // login successful
            this.currentUser = credentials;
            //vamos a home
            observer.next(true);
            observer.complete();
                                 } else {
            // login failed
            this.currentUser = credentials;
            // Volvemos a pedir la introducción de los datos.
            observer.next(false);
            observer.complete();
                                  }
                             });
                         });
                     }
                   }
               
        
    Para subdividir el proceso de comunicación de la lógica de logueo, he creado el fichero providers/comunicaciones/comunicaciones.ts donde el método login_web tiene el método de comunicación post con el servidor web.
         
    
               //método de comunicación con el servicio web alojado en multimedia.uoc.edu.
           login_Web(username: string, password: string): Observable<boolean> {
            //alert(username);
            const params: URLSearchParams = new URLSearchParams();
            params.set('user', username);
            params.set('passwd', password);
            return this.http.post(
              'http://multimedia.uoc.edu/frontend/auth.php', params)
              .map((response: Response) => {
                      if (response.json().status.localeCompare('OK') === 0) {
            return true;
                       } else {
            return false;
                       }
                 });
               }
        

    ionic 4 o ionic 5

    En el proyecto en blanco ejecutaremos el siguiente comando.

         
               ionic g service services/comunicaciones
               
        

    En la nueva versión, el código resultante modificado quedaría así:
             
             import { Injectable } from '@angular/core';
             import {User} from '../models/user';
    
    
             @Injectable({
            providedIn: 'root'
             })
             export class ComunicacionesService {
            public user: User;
    
    
          constructor() {
               try {
            const currentUser = JSON.parse(localStorage.getItem('currentUser'));
               } catch (e) {
            const currentUser = '';
               }
             }
    
             login(username: string, password: string): boolean {
               const xhr = new XMLHttpRequest();
               const data = {
            'user': username,
            'passwd': password
               };
               localStorage.clear();
               xhr.open('POST', 'http://multimedia.uoc.edu/frontend/auth.php', false);
               xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
               xhr.onload  = function() {
            return xhr.response;
            // do something with jsonResponse
               };
               xhr.send('user=demo&passwd=demo');
               if ( JSON.parse(xhr.responseText).status  !== 'OK') {
            return false;
               } else {
            this.user = new User(username, password);
            localStorage.setItem('currentUser', this.user.to_json() );
            return true;
               }
             }
    
    
             logout(): void {
               localStorage.setItem('currentUser', '');
               localStorage.removeItem('currentUser');
             }
    
    
             }
             
    

    En este momento he decidido unificar ambas funciones y directamente crear un único fichero con todo el contenido. También he utilizado el método XMLHttpRequest para realizar las comunicaciones con la API en sustitución del http
  • Añadimos un estilo en el componente tabs con el objetivo de modificar el estilo por defecto.
    • Modificación del color del fondo del tab. Para ello he modificado el fichero pages/tabs/tabs.scss
            
                     .tabs-md .tabbar{
                  background-color: #9cff00 !important;
                     } 
           
    • Añadir una opción extra en el tab. Para ello he añadido en el fichero pages/tabs/tabs.html el siguiente código.
            
                     <ion-tab [root]="tab4Root" tabIcon="exit" tabTitle="Logout"></ion-tab> 
           
      Además he modificado el fichero pages/tabs/tabs.ts añadiendo la nueva pagina creada.
             tab4Root = LogoutPage; 
           
    • Crear un icono para el Tab. Para ello he modificado el fichero pages/tabs/tabs.scss
            
                     .ion-ios-exit,.ion-md-exit{
                  content: url(../../images/exit.svg);
                  width: 24px;
                  height: 32px;
                  padding: 6px 4px 2px;
                 opacity: 0.9;
                 }
           
    • Pruebas con scss. Para generar diferentes pruebas con la utilización del compilador scss he modificado los siguientes ficheros
      • pages/home/home.scss: Mediante un método set-notification-text-color adapto el color del texto al fondo del objeto que lo contiene. Además cree una clase de notificación para optimizar el código.
                
                           //ejemplo de función de scss que modifica  el color del texto dependiendo del fondo.
                           @function set-notification-text-color($color) {
                        @if (lightness($color) > 50) {
                                       @return #000000; // Lighter backgorund, return dark color
                               } @else {
                                       @return #ffffff; // Darker background, return light color
                               }
                           }
        
                           page-home {
                        //creo las variables con los colores
                        $notification-confirm: hsla(101, 72%, 37%, 1);  // Green
                        $notification-warning: #ffc53a;                 // Yellow
                        $notification-alert: rgb(172, 34, 34);          // Red
        
                       //clase  notificacion
                       %notification {
                               border-radius: 10px;
                               display: block;
                               font-size: 1.5em;
                               font-family: sans-serif;
                               padding: 1em 2em;
                               margin: 1em auto;
                               width: 30%;
                               text-align: center;
                               }
        
                             .notification {
                               @extend %notification;
                               }
        
                             //genero los diferentes  objetos notificacion con un color de la letra adaptado al nombre.
                             .notification-confirm {
                               background: $notification-confirm;
                               color: set-notification-text-color($notification-confirm);
                             }
        
                             .notification-warning {
                               background: $notification-warning;
                               color: set-notification-text-color($notification-warning);
                               }
        
                             .notification-alert {
                               background: $notification-alert;
                               color: set-notification-text-color($notification-alert);
                               }
        
                             }
                           
               
      • pages/login/login.scss: En este documento he aplicado varias modificaciones CSS básicas.
                
                           page-login {
                        .login-content {
                                 background: #56CA96;
        
                                 .logo-row {
                        padding-top: 50px;
                        padding-bottom: 20px;
                                 }
        
                                 .login-box {
                        background: #399F8B;
                        padding: 20px 20px 0px 20px;
                        margin-top: 30px;
                                 }
        
                                 ion-row {
                        align-items: center;
                        text-align: center;
                                 }
        
                                ion-item {
                        //redonde los text box
                        border-radius: 30px !important;
                        padding-left: 30px !important;
                        font-size: 0.9em;
                        margin-bottom: 10px;
                        border: 1px solid #ffffff;
                        border-bottom: 0px !important;
                        box-shadow: none !important;
                                }
        
                               .signup-col {
                        margin: 0px 16px 0px 16px;
                        padding-bottom: 20px;
                               }
        
                               .item-inner {
                        border-bottom-color: #ffffff !important;
                        box-shadow: none !important;
                               }
        
                               .submit-btn {
                        background: #51CFB1;
                        border-radius: 30px !important;
                        border: 1px solid #ffffff;
                               }
        
                               .register-btn {
                        color: #ffffff;
                        font-size: 0.8em;
                               }
                             }
                           }
                           
               
    • Función de desconexión La nueva opción del tab permite la desconexión del usuario, pero no está correctamente implementada. Actualmente, la aplicación no tiene en cuenta que usuario esta logueado, y su lógica únicamente se basa en redirigir al usuario a la página de login. El código esta disponible en pages/logout/logout.ts:
            
                     ionViewDidLoad() {
                  this.navCtrl.push('LoginPage');
                  location.assign('/');
                     }
                     
           

Códigos Github

Los códigos expuestos son consultables en las siguientes direcciónes

Si necesitas ayuda esta disponible el siguiente video explicativo: https://www.youtube.com/watch?v=CUsklt966rA.