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.
- Ejecuta
- Angular CLI (
npm install -g @angular/cli@latest
para instalar).- Ejecuta
ng --version
para verificar que tienes versión 10 o más.
- Ejecuta
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
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
En el directorio del proyecto, puedes iniciar el servidor de desarrollo usando ng serve
:
ng serve
** 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
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%;
}
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>
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
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
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
💡 El comando
ng generate
admite un acceso directo: Usang 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>
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';
Agrega RouterModule
a el array de imports:
@NgModule({
declarations: [LayoutComponent, HeaderComponent, FooterComponent],
imports: [CommonModule, RouterModule],
})
💡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>
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
],
},
];
Asegurate de importar LayoutComponent
en src/app/app-routing.module.ts
:
import { LayoutComponent } from './ui/layout/layout.component';
Abre src/app/app.component.html
y reemplaza el contenido con la siguiente línea:
<router-outlet></router-outlet>
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>
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 © 2020</small>
</div>
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
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>
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),
},
],
},
];
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
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>
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
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';
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(['/']);
}
}
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>
💡 El template del
LoginComponent
es bastante largo. Cuando agregues más páginas de autenticación, considera crear unAuthLayoutComponent
separado y usalo comoLayoutComponent
, luego agregaLoginComponent
,RegisterComponent
etc, como elementos secundarios deAuthLayoutComponent
.
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
];
¿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';
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)
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
~~~~~~~~~~~~~~~~~~
Can you help me?
Thks.
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!!