DEV Community

Derlys for kikstart.dev

Posted on • Edited on

Tutorial: Aplicaciones de Angular CLI con bootstrap

Example of the pages of the final app

En este tutorial, tu aprendes cómo usar estilos en Apps de Angular CLI.

La meta es construir un layout en una aplicación con un header y un footer, una página home, página about y una página login con formulario.

Mira el demo en vivo aquí o el repositorio de Github.

Requisitos

Asegurate que tienes la siguientes herramientas instaladas:

  • Node.js y NPM, visita su pagina web para las instrucciones de instalación.
    • Ejecuta node -v para verificar que tienes versión 12 o más.
    • Ejecuta npm -v para verificar que tienes la versión 6 o más.
  • Angular CLI ( npm install -g @angular/cli@latest para instalar).
    • Ejecuta ng --version para verificar que tienes versión 10 o más.

Si prefieres usar yarn, primero configura el package manager de Angular CLI . Esto asegura que la aplicación esta creado con un archivo yarn.lock en vez de un package-lock.json.

1. Crea una nueva aplicación

Abre un terminal y ejecuta el siguiente comando:



ng new sandbox --routing --style scss --strict


Enter fullscreen mode Exit fullscreen mode

El comando ng new genera una aplicación Angular básica en un directorio llamado sandbox e instala sus dependencias.

El --routing le indica a Angular CLI que se genere un módulo de rutas.
El --style scss indica que usamos SCSS para los estilos.
El --strict configura la aplicación para ejecutarse en modo estricto.

Al final de la instalación del app, el Angular CLI también inicializa un repositorio de git y hace un commit inicial.

2. Inicia la aplicación en modo de desarrollo

Después de haber finalizado la instalación, ejecuta el siguiente comando para navegar al directorio del proyecto.



cd sandbox


Enter fullscreen mode Exit fullscreen mode

En el directorio del proyecto, puedes iniciar el servidor de desarrollo usando ng serve:



ng serve


Enter fullscreen mode Exit fullscreen mode

** Angular Live Development Server is listening on localhost:4200, open your browser on (http://localhost:4200/) **

Navega al link mencionado antes por el servidor de desarrollo y verifica que esté funcionando. El app está lista para tener algunos estilos!  😎

3. Instala Bootstrap

Ejecuta el siguiente comando en el directorio de tu proyecto para instalar Bootstrap:



npm install bootstrap


Enter fullscreen mode Exit fullscreen mode

Cuando la instalación finaliza podemos decirle a Angular CLI que use estos estilos.

Abre src/styles.scss y agrega las siguientes líneas:



@import '~bootstrap/scss/bootstrap';
// Set the full page height so we can stick the footer to the bottom
html,
body {
  height: 100%;
}


Enter fullscreen mode Exit fullscreen mode

Después abre src/app/app.component.html y borra todo el contenido,reemplazalo con lo siguiente:



<h1 class="text-center text-primary">Hello Bootstrap!</h1>


Enter fullscreen mode Exit fullscreen mode

Cuando regreses a tu navegador, deberías ver Hello Bootstrap en letras azules grandes 👏🎊.

¡Podemos hacer que nuestra aplicación se vea mejor!

4. Configura el layout de la aplicación

The basic application layout

En este paso creamos un UiModule y le agregamos 3 componentes:

LayoutComponent, HeaderComponent, y FooterComponent.

💡Es una buena idea mantener el UI separado del resto de la app. Esta separación de responsabilidades también te permite fácilmente reutilizar el UI en otros proyectos.

4.1 Crea el UiModule

Ejecuta el siguiente comando para generar el UiModule.



ng generate module ui --module app


Enter fullscreen mode Exit fullscreen mode

Despues, genera los 3 componentes dentro de este nuevo módulo:



ng generate component ui/layout
ng generate component ui/header
ng generate component ui/footer


Enter fullscreen mode Exit fullscreen mode

💡 El comando ng generate admite un acceso directo: Usa ng g c para generar un componente, ng g m para generar un módulo, etc.

4.2 Implementa Layout Component

Abre src/app/ui/layout/layout.component.html y reemplaza el contenido con el siguiente pedazo de código:



<!-- This flex container takes the full height -->
<div class="d-flex flex-column h-100">
  <app-header></app-header>
  <!-- The main area does not shrink, 'pushing down' the footer -->
  <main class="flex-shrink-0">
    <!-- This will render the routes -->
    <router-outlet></router-outlet>
  </main>
  <!-- This keeps the footer down if the main content does not fill up the space -->
  <footer class="mt-auto">
    <app-footer></app-footer>
  </footer>
</div>


Enter fullscreen mode Exit fullscreen mode

Podemos usar este LayoutComponent en la ruta, y renderizar los children en la ubicación de router-outlet.

Antes de seguir, asegurate de importar RouterModule en UiModule.

Abre src/app/ui/ui.module.ts y agrega el siguiente código después de los otros imports:



import { RouterModule } from '@angular/router';


Enter fullscreen mode Exit fullscreen mode

Agrega RouterModule a el array de imports:



@NgModule({
  declarations: [LayoutComponent, HeaderComponent, FooterComponent],
  imports: [CommonModule, RouterModule],
})


Enter fullscreen mode Exit fullscreen mode

💡Si olvidas el import de RouterModule, el servidor te dira:

ERROR in src/app/ui/layout/layout.component.html:3:3 - error NG8001: 'router-outlet' is not a known element:
  1.  If 'router-outlet' is an Angular component, then verify that it is part of this module.
  2.  If 'router-outlet' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.</pre>
Enter fullscreen mode Exit fullscreen mode

4.3 Usa el LayoutComponent

Abre src/app/app-routing.module.ts y reemplaza la linea const routes: Routes = [] con lo siguiente:



const routes: Routes = [
  {
    path: '',
    component: LayoutComponent,
    children: [
      // Here we will add our application pages
    ],
  },
];


Enter fullscreen mode Exit fullscreen mode

Asegurate de importar LayoutComponent en src/app/app-routing.module.ts:



import { LayoutComponent } from './ui/layout/layout.component';


Enter fullscreen mode Exit fullscreen mode

Abre src/app/app.component.html y reemplaza el contenido con la siguiente línea:



<router-outlet></router-outlet>


Enter fullscreen mode Exit fullscreen mode

Guarda todos los archivos y revisa en tu navegador, deberías ver el HeaderComponent y FooterComponent renderizados. Hora de decorarlas!

4.4 Implementa el Header

Abre src/app/ui/header/header.component.html y reemplaza el contenido con lo siguiente:



<!-- You can change the values `dark` here with any of the following: -->
<!-- dark, light, primary, secondary, success, info, danger, warning -->
<nav class="navbar navbar-dark bg-dark">
  <!-- This is the application title with a link to the root -->
  <a class="navbar-brand" routerLinkActive="active" routerLink="/">Angular & Bootstrap</a>
  <!-- This is a spacer so the links move to the end -->
  <div class="mr-auto"></div>
  <!-- This main navigation links are defined here -->
  <div class="navbar-expand">
    <div class="navbar-nav">
      <!-- Each link has the routerLink property set to a different route -->
      <a class="nav-item nav-link" routerLinkActive="active" routerLink="/home">Home</a>
      <a class="nav-item nav-link" routerLinkActive="active" routerLink="/about">About</a>
      <a class="nav-item nav-link" routerLinkActive="active" routerLink="/login">Login</a>
    </div>
  </div>
</nav>


Enter fullscreen mode Exit fullscreen mode

Refiere a la documentación de navbar en bootstrap para mas detalles de la sintaxis del navbar y como hacerlos responsivo.

4.5 Implementa el Footer

Abre src/app/ui/footer/footer.component.html y reemplaza el contenido con esto:



<div class="py-3 bg-dark text-center text-muted">
  <small>Copyright &copy; 2020</small>
</div>


Enter fullscreen mode Exit fullscreen mode

5. Agregar páginas de aplicación

Cuando el layout de la aplicación esté en su lugar, es el momento de agregar unas páginas.

El comando que usamos crea un módulo con un componente y usa lazy-loading para registrarlo en el AppModule.

💡Lazy loading es recomendado como una manera de enrutar en una app de Angular, ya que se asegura que los usuarios no descarguen código que no se usará.

5.1 Crea una pagina Home

Ejecuta el siguiente comando para generar el HomeModule:



ng g module pages/home --route home --module app


Enter fullscreen mode Exit fullscreen mode

Abre src/app/pages/home/home.component.html y reemplaza el contenido con esto:



<div class="container py-5">
  <div class="jumbotron">
    <h1 class="text-secondary">Home</h1>
  </div>
</div>


Enter fullscreen mode Exit fullscreen mode

Ve a la aplicación en el navegador y haz clic en el enlace Home en el header.

Te llevará a la ruta /home con el texto 'Home'. Sin embargo, el layout con el header y el footer se ha ido!

Para arreglar esto, abre src/app/app-routing.module.ts y mueve la ruta creada recientemente dentro del array children.



const routes: Routes = [
  {
    path: '',
    component: LayoutComponent,
    children: [
      // Here we will add our application pages
      {
        path: 'home',
        loadChildren: () => import('./pages/home/home.module').then(m => m.HomeModule),
      },
    ],
  },
];


Enter fullscreen mode Exit fullscreen mode

Después de guardar este archivo, la pagina deberia renderizarse apropiadamente.

5.2 Crea la pagina About

Ejecuta el siguiente comando para generar el AboutComponent:



ng g module pages/about --route about --module app


Enter fullscreen mode Exit fullscreen mode

Abre src/app/pages/about/about.component.html y reemplaza el contenido con esto:



<div class="container py-5">
  <div class="jumbotron">
    <h1 class="text-secondary">About</h1>
  </div>
</div>


Enter fullscreen mode Exit fullscreen mode

Abre src/app/app-routing.module.ts y mueve la ruta de about dentro del array children para que se encuentre al lado de la ruta de HomeModule.

5.3 Crea la pagina Login

La página de login es un poco más compleja porque tiene un formulario y usa el router para redirigir el usuario.

Ejecuta el siguiente comando para generar el LoginModule:



ng g module pages/login --route login --module app


Enter fullscreen mode Exit fullscreen mode

Abre src/app/pages/login/login.component.ts y agrega el siguiente codigo despues de los otros imports:



import { FormControl, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';


Enter fullscreen mode Exit fullscreen mode

Cambia el contenido del cuerpo de la clase LoginComponent con esto:



export class LoginComponent implements OnInit {
  // The form group defines the fields used in the form
  form = new FormGroup({
    email: new FormControl(''),
    password: new FormControl(''),
  });

  // Inject the router so we can navigate after a successful login
  constructor(private readonly router: Router) {}

  ngOnInit(): void {}

  public submit() {
    // Use the form value to do authentication
    console.log(this.form.value);
    // Navigate after successful login
    return this.router.navigate(['/']);
  }
}


Enter fullscreen mode Exit fullscreen mode

Abre src/app/pages/login/login.component.html y reemplaza el contenido con lo siguiente:



<!-- This flex container takes the full height and vertically centers the content -->
<div class="d-flex flex-column h-100 justify-content-center">
  <div class="container">
    <div class="row">
      <!-- This is a single column that is responsive -->
      <div class="col-12 col-md-6 offset-md-3">
        <div class="card">
          <div class="card-header">Login</div>
          <div class="card-body">
            <!-- The formGroup 'form' is defined in the component class -->
            <form [formGroup]="form">
              <div class="form-group">
                <label for="email">Email address</label>
                <!-- The formControlName defines the name of the field in the formGroup -->
                <input id="email" formControlName="email" type="email" required class="form-control" />
              </div>
              <div class="form-group">
                <label for="password">Password</label>
                <input id="password" formControlName="password" type="password" required class="form-control" />
              </div>
            </form>
          </div>
          <div class="card-footer">
            <div class="d-flex justify-content-between">
              <a routerLink="/" class="ml-2 btn btn-outline-secondary">
                Home
              </a>
              <!-- The button has a click handler, it will be disabled if the form is not valid -->
              <button (click)="submit()" [disabled]="!form.valid" type="submit" class="btn btn-outline-success">
                Log in
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>


Enter fullscreen mode Exit fullscreen mode

💡 El template del LoginComponent es bastante largo. Cuando agregues más páginas de autenticación, considera crear un AuthLayoutComponent separado y usalo como LayoutComponent, luego agrega LoginComponent, RegisterComponent etc, como elementos secundarios de AuthLayoutComponent.

Ve a tu aplicación en el navegador y da clic al enlace Login en el header.

La página de login renderiza el formulario en el centro de la pantalla y no necesitamos agregar la ruta en el array de children.

Hay una última cosa por arreglar. Si haces clic en el enlace Home, volverá a la raíz de la aplicación que está en blanco.

¿ No sería genial si pudiéramos ir a la página de inicio 😱?

5.4 Redirigir la ruta inicial

Abre src/app/app-routing.module.ts y agregar el siguiente objeto en la parte superior del array de rutas:



const routes: Routes = [
  {
    path: '',
    // If this path is the 'full' match...
    pathMatch: 'full',
    // ...redirect to this route.
    redirectTo: 'home',
  },
  // The other routes go here
];


Enter fullscreen mode Exit fullscreen mode

¿A dónde ir desde aquí?

Como se indicó en la introducción, esta aplicación es un punto de partida y debería ser bastante sencilla para mejorarla a tu gusto.

Librerías adicionales

Usa ng-bootstrap o ngx-bootstrap si deseas usar implementaciones de los componentes de bootstrap, como menús desplegables, pestañas, colapsar, etc. Ambas librerías son excelentes opciones, elija la que más le guste.

Si tus aplicaciones tienen muchos formularios, usa formly para una forma declarativa de definir sus formularios, sin escribir ninguna de las plantillas de formulario.

Temas y colores

Para ajustar la apariencia de Bootstrap, abre src/styles.scss y configura las variables. Asegúrate de definir las variables antes de importar Bootstrap:



$dark: hotpink;
$jumbotron-bg: #333;
$secondary: limegreen;
$body-bg: #555;
@import '~bootstrap/scss/bootstrap';


Enter fullscreen mode Exit fullscreen mode

Otra opción genial es Bootswatch, que ofrece más de 20 diseños diferentes basados en bootstrap.

Conclusión

En este tutorial, tu aprendiste cómo crear una aplicación básica de Angular y usaste bootstrap para crear un layout con header y footer.

La app tiene varias páginas que son lazy loaded. La página de login tiene un formulario con validación básica y un redireccionamiento a la página de Home.

En caso que tengas alguna pregunta, siéntete libre para comentar en DEV o enviame un mensaje a mi twitter!

Muchas gracias por leerme y hagan mucho código 🤓

Top comments (2)

Collapse
 
excepticons profile image
excepticons

Hi.
I'm getting this compiler error in step of Login component when paste the code html:

Error: src/app/pages/login/login.component.html:11:19 - error NG8002: Can't bind to 'formGroup' since it isn't a known property of 'form'.
11


~~~~~~~~~~~~~~~~~~
  src/app/pages/login/login.component.ts:7:16
    7   templateUrl: './login.component.html',
                     ~~~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component LoginComponent.

Can you help me?

Thks.

Collapse
 
santi72alc profile image
Santiago San Román • Edited

I had the same problem...
I fixed it modifying 'login.module.ts'
add the next import
import { ReactiveFormsModule } from '@angular/forms';

and the problem was fixed for me.
Good luck!!