Angular6 + Material – Corrección de un tutorial

Recientemente estuve tratando de aprender sobre Angular 6 y Material como plataforma para crear aplicaciones web con componentes de interfaz de usuario avanzados.

Me topé con este tutorial que me pareció sencillo  pero a la vez me dio algunos dolores de cabeza por cambios que han ocurrido en el ecosistema de Angular que hacen que algunos pasos del tutorial no funcionen.

Bien, seguidamente presento algunas de las correcciones que tuve que realizar para que funcionara.
El primer paso del tutorial es crear una nueva aplicación Angular usando el cliente de consola ng. Este es un paso muy sencillo.

ng new ngMat01

Funciona sin problema. Para ver el contenido predeterminado de esta aplicación basta con entrar a la carpeta ngMat01 y ejecutar el comando serve.

cd ngMat01

ng serve --open

El segundo paso consiste en agregar angular-material al proyecto usando la herramienta de consola ng . Este paso fracasa porque el archivo angular.json predeterminado de nuestra nueva aplicación viene con un formato que no es el que el instalador  de material (le llaman schematic) espera.

Así que antes de agregar material a nuestro proyecto vamos a editar el archivo angular.json y vamos a cambiar el nombre de uno de los objetos descritos en el archivo que se llama “targets” a un nuevo nombre “architect“. El nodo a cambiar está en projects > ngMat01 > targets.

Seguidamente muestro un ejemplo de como puede quedar dicho archivo. Recomiendo no usar el archivo directamente sino renombrar targets del archivo que haya obtenido en su instalación. Esto para no perder nuevos cambios que hayan ocurrido en el generador de proyectos de Angular luego de escribir este artículo. Ver línea 12 del archivo de ejemplo.

Haz clic acá para ver un ejemplo del archivo
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "ngMat01": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "app",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/ngMat01",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "ngMat01:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "ngMat01:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "ngMat01:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.spec.json",
            "karmaConfig": "src/karma.conf.js",
            "styles": [
              "src/styles.css"
            ],
            "scripts": [],
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ]
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "src/tsconfig.app.json",
              "src/tsconfig.spec.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }      
    },
    "ngMat01-e2e": {
      "root": "e2e/",
      "projectType": "application",
      "targets": {
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "ngMat01:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "ngMat01:serve:production"
            }
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": "e2e/tsconfig.e2e.json",
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    }
  },
  "defaultProject": "ngMat01"
}

Una vez realizado este cambio ya se podrá agregar Material a nuestro proyecto usando el comando propuesto:

ng add @angular/material

Los siguientes comandos tambien fallaban por causa de la entrada “target” del archivo angular.json, así que a estas alturas no debería haber problema con ellos. Básicamente se generan nuevos componentes basados en los generadores (schematics) de material; sin embargo, al parecer en los schematics de material han cambiado los nombres de los componentes para usar un estandard definido. Así que los comandos variarán un poco. Los que funciona son estos:

ng generate @angular/material:material-nav --name myNav
ng generate @angular/material:material-dashboard --name myDashboard
ng generate @angular/material:material-table --name myTable

En el tutorial estos comandos buscan generar componentes basados en schematics de nombre materialNav, materialDashboard y materialTable; los nombres correctos a este momento son material-nav. material-dashboard y material-table. Otro aspecto interesante fue comprobar que en el tutorial el tercer comando tiene un espacio entre y name, lo cual malogra el comando.

Una vez generados los componentes básicos, el tutorial indica que hay que editar el archivo de plantilla de vista app.component.html  para quitar todo el código predeterminado y reempalzarlo por la línea <my-nav></my-nav>. Esto tampoco funcina. La línea correcta se describe a continuación.

<app-my-nav></app-my-nav>

Antes de continuar es necesario asegurarse de que el archivo /src/styles.css contiene la siguiente línea; la cual importa a nuestra aplicación uno de los temas predefinidos de material.

@import "~@angular/material/prebuilt-themes/indigo-pink.css";

Ahora si, en este punto nuestro sistema no debería tener ningún problema en ejecutarse con ng serve –open y mostrar el siguiente contenido estilizado en un navegador; el cual no solamente incluye una bonita disposición de componentes sino las animaciones y reacciones propias de una interfaz de usuario flexible.

Las siguientes dos imágenes muestran el resultado.

Imagen de Pantalla Completa. Muestra una barra de herramientas y un Menú 

Imagen de pantalla angosta. Muestra la barra de herramientas. El menú ha sido colapsado dentro de un control tipo “hamburguesa”

Al hacer clic al control tipo “hamburguesa” el sistema oscurece la pantalla y muestra el contenido del menú.

De hecho, si seguimos el tutorial completo, podemos acabar con un resultado que incluye enrutamiento y uso de otros elementos de Material, tal y como se aprecia en la siguiente imagen.

366 total views, 2 views today

6Shares

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

This site uses Akismet to reduce spam. Learn how your comment data is processed.