Angular

Angular

Tutorial Angular: Componentes standalone

Angular componentes standalone: creación y uso. Aprende a crear y usar componentes standalone en Angular con ejemplos prácticos y detallados.

Una de las innovaciones más significativas introducidas en las versiones recientes de Angular es el concepto de componentes standalone (autónomos). 

Esta funcionalidad representa un cambio paradigmático en la forma de estructurar y modular las aplicaciones Angular, ofreciendo una aproximación más simplificada y eficiente al desarrollo. 

Definición y características

Un componente standalone en Angular es aquel que se declara de manera independiente, sin necesidad de asociarse a un módulo específico de Angular (NgModule)

Tradicionalmente, Angular ha utilizado módulos para organizar y agrupar componentes, directivas y servicios. Sin embargo, los componentes standalone rompen con esta dependencia, permitiendo una mayor flexibilidad y modularidad.

Para declarar un componente standalone, se utiliza el decorador @Component de Angular, especificando la propiedad standalone como true

Además, dentro de esta declaración, es posible importar directamente otros componentes, directivas y pipes que el componente autónomo requiera para su funcionamiento. 

Por ejemplo:

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CustomComponent } from './custom-component';
import { CustomPipe } from './custom-pipe';

@Component({
  selector: 'app-standalone-example',
  standalone: true, // esta línea es que la que hace que el componente sea standalone
  imports: [CommonModule, CustomComponent, CustomPipe],
  templateUrl: './standalone-example.component.html',
  styleUrls: ['./standalone-example.component.css']
})
export class StandaloneExampleComponent {
  // La lógica del componente aquí
}

Beneficios de los componentes standalone

  • Modularidad mejorada: Al ser autocontenidos, facilitan una mejor organización del código, permitiendo que los componentes sean más reusables y portables.
  • Simplificación de la estructura de la aplicación: Reducen la necesidad de módulos NgModules, que pueden ser complicados de manejar en aplicaciones grandes. Esto lleva a una estructura de aplicación más simple y fácil de entender.
  • Optimización del rendimiento: Al poder cargar solo los componentes necesarios para una vista o funcionalidad específica, se puede mejorar el rendimiento de la aplicación al reducir el tamaño del código que necesita ser cargado e interpretado.
  • Desarrollo y testing más sencillo: Los componentes autónomos son más fáciles de probar ya que son independientes de otros componentes y módulos de la aplicación.
  • Mejor tree-shaking: Facilitan la eliminación de código no utilizado, resultando en bundles más pequeños.

Integración con otras características de Angular

Routing

La integración con el sistema de routing de Angular es clave para construir aplicaciones SPA (Single Page Applications). Los componentes standalone pueden ser utilizados como componentes de ruta, permitiendo que sean cargados dinámicamente como parte de la configuración de rutas de Angular. Esto facilita la construcción de rutas más limpias y modulares, potencialmente mejorando el lazy loading y la segmentación de código.

const routes: Routes = [
  {
    path: 'feature',
    loadComponent: () => import('./feature/feature.component').then(m => m.FeatureComponent)
  }
];

Signals

Signals representa una evolución significativa en el manejo del estado y la reactividad en Angular. Para los componentes standalone, Signals ofrece una forma más eficiente y predecible de manejar datos reactivos sin la necesidad de librerías externas de gestión de estado.

Ejemplo extendido de uso de Signals en un componente standalone:

import { Component, computed, effect, signal } from '@angular/core';

@Component({
  selector: 'app-todo-list',
  standalone: true,
  template: `
    <h2>Todo List ({{ incompleteTasks() }} pending)</h2>
    <ul>
      <li *ngFor="let task of tasks()">
        <input type="checkbox" [checked]="task.completed" (change)="toggleTask(task)">
        {{ task.title }}
      </li>
    </ul>
    <button (click)="addTask('New Task')">Add Task</button>
  `
})
export class TodoListComponent {
  tasks = signal<Array<{id: number, title: string, completed: boolean}>>([
    {id: 1, title: 'Learn Angular', completed: false},
    {id: 2, title: 'Master Signals', completed: false}
  ]);

  incompleteTasks = computed(() => this.tasks().filter(task => !task.completed).length);

  constructor() {
    effect(() => {
      console.log(`There are now ${this.incompleteTasks()} incomplete tasks.`);
    });
  }

  addTask(title: string) {
    this.tasks.update(tasks => [
      ...tasks, 
      {id: tasks.length + 1, title, completed: false}
    ]);
  }

  toggleTask(taskToToggle: {id: number, completed: boolean}) {
    this.tasks.update(tasks => 
      tasks.map(task => 
        task.id === taskToToggle.id 
          ? {...task, completed: !task.completed} 
          : task
      )
    );
  }
}

En este ejemplo:

  • Usamos signal() para crear un estado reactivo para nuestra lista de tareas.
  • computed() se utiliza para derivar el número de tareas incompletas, que se recalcula automáticamente cuando cambia el estado de las tareas.
  • effect() se emplea para ejecutar efectos secundarios, en este caso, registrar en consola cuando cambia el número de tareas incompletas.
  • Los métodos addTask() y toggleTask() utilizan la API de actualización de Signals para modificar el estado de manera inmutable.

Importaciones optimizadas

En versiones recientes de Angular, se ha introducido una mejora significativa en la forma de importar funcionalidades comunes. En lugar de importar todo el CommonModule, ahora se recomienda importar específicamente las directivas y pipes que se necesitan. Esto contribuye a una mejor optimización y un tree-shaking más eficiente.

import { Component } from '@angular/core';
import { NgIf, NgFor } from '@angular/common';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [NgIf, NgFor],
  template: `
    <div *ngIf="showContent">
      <ul>
        <li *ngFor="let item of items">{{ item }}</li>
      </ul>
    </div>
  `
})
export class ExampleComponent {
  showContent = true;
  items = ['Item 1', 'Item 2', 'Item 3'];
}

Esta práctica permite que el compilador incluya solo el código necesario, reduciendo el tamaño final del bundle y mejorando el rendimiento de la aplicación.

Servicios

Los componentes standalone pueden inyectar servicios de la misma manera que los componentes tradicionales, aprovechando la inyección de dependencias de Angular.

Inyección de dependencias

Se ha simplificado la inyección de dependencias en componentes standalone, permitiendo el uso de inject() en lugar de constructores para una sintaxis más limpia.

import { Component, inject } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app-user-profile',
  standalone: true,
  template: `<p>Welcome, {{ userName() }}</p>`
})
export class UserProfileComponent {
  private userService = inject(UserService);
  userName = this.userService.getUserName();
}

Ejemplo práctico

Aquí se muestra cómo se podría estructurar un botón y un formulario como componentes standalone dentro de una biblioteca de componentes de UI.

Botón Standalone

// button.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'ui-button',
  standalone: true,
  template: `<button><ng-content></ng-content></button>`,
  styleUrls: ['./button.component.css']
})
export class ButtonComponent {
  // Lógica del botón aquí
}

Formulario Standalone

// form.component.ts
import { Component } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { ButtonComponent } from './button.component'; // Asumiendo que ButtonComponent es otro componente standalone

@Component({
  selector: 'ui-form',
  standalone: true,
  imports: [ReactiveFormsModule, ButtonComponent],
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.css']
})
export class FormComponent {
  // Lógica del formulario aquí
}
<!-- form.component.html -->
<form>
  <!-- Campos del formulario aquí -->
  <ui-button>Enviar</ui-button>
</form>

Este ejemplo ilustra cómo los componentes pueden ser diseñados como standalone y luego reutilizados a través de diferentes aplicaciones o proyectos. Al hacer que el ButtonComponent y el FormComponent sean standalone, estos pueden ser importados directamente donde se necesiten sin preocuparse por la configuración de módulos NgModules tradicionales. Esto es especialmente útil para bibliotecas de UI, donde se desea ofrecer componentes que puedan ser fácilmente integrados en cualquier proyecto Angular.

La clave de la reutilización efectiva de componentes en Angular, especialmente con los componentes standalone, radica en diseñarlos de manera que sean lo más independientes y encapsulados posible. Esto incluye asegurarse de que manejen sus dependencias, estilos y lógica interna de manera autónoma, facilitando así su integración en diversos contextos sin conflictos ni necesidades de configuración adicional.

Mejores prácticas para componentes standalone

  1. Diseño modular: Crea componentes pequeños y enfocados que realicen una tarea específica.
  2. Reutilización: Diseña componentes pensando en su reutilización en diferentes partes de la aplicación o incluso en otros proyectos.
  3. Gestión de estado: Utiliza Signals para manejar el estado interno del componente de manera eficiente.
  4. Lazy loading: Aprovecha la capacidad de carga perezosa para optimizar el rendimiento de la aplicación.
  5. Testabilidad: Escribe pruebas unitarias para tus componentes standalone aprovechando su naturaleza independiente.
Certifícate en Angular con CertiDevs PLUS

Ejercicios de esta lección Componentes standalone

Evalúa tus conocimientos de esta lección Componentes standalone con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Signals en Angular

Angular
Puzzle

Guards funcionales

Angular
Test

Decodificar JWT en Angular

Angular
Test

Servicio con HttpClient

Angular
Código

Ciclo de vida de componentes en Angular

Angular
Test

Gestión de productos de Fake Store API

Angular
Proyecto

Data binding en Angular

Angular
Test

Routes sin módulos en Angular

Angular
Código

Router en Angular

Angular
Test

Instalación de Angular

Angular
Puzzle

Route Guards basados en interfaces

Angular
Código

La directiva @if en Angular

Angular
Puzzle

Formularios reactivos en Angular

Angular
Código

Servicios en Angular

Angular
Puzzle

Interceptor funcional

Angular
Test

Servicio con Array

Angular
Código

La directiva @for en Angular

Angular
Puzzle

Interceptores HTTP

Angular
Código

Componentes standalone true

Angular
Puzzle

Formularios con ngModel en Angular

Angular
Puzzle

Routes en Angular

Angular
Test

Comunicación entre componentes Angular

Angular
Test

Parámetros en rutas con ActivatedRoute

Angular
Test

CRUD de Restaurantes y Platos

Angular
Proyecto

Tablas en Angular Material

Angular
Puzzle

Formulario de registro de usuarios

Angular
Proyecto

Instalación y uso de NgBoostrap

Angular
Puzzle

Desarrollo de componentes Angular

Angular
Test

JWT en Angular

Angular
Código

Formularios reactivos en Angular

Angular
Puzzle

Formularios en Angular Material

Angular
Puzzle

Layout con Angular Material

Angular
Puzzle

Effects en Angular

Angular
Test

Data binding

Angular
Código

HttpClient en servicios de Angular

Angular
Puzzle

Desarrollo de módulos Angular

Angular
Puzzle

Comandos Angular CLI

Angular
Puzzle

Subir archivo en formularios

Angular
Test

La directiva routerLink en Angular

Angular
Test

Todas las lecciones de Angular

Accede a todas las lecciones de Angular y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Instalación Angular

Angular

Introducción Y Entorno

Comandos Angular Cli

Angular

Introducción Y Entorno

Desarrollo De Componentes Angular

Angular

Componentes

Data Binding En Angular

Angular

Componentes

Ciclo De Vida De Componentes En Angular

Angular

Componentes

Comunicación Entre Componentes Angular

Angular

Componentes

La Directiva @If En Angular

Angular

Componentes

La Directiva @For En Angular

Angular

Componentes

Componentes Standalone

Angular

Componentes

Desarrollo De Módulos Angular

Angular

Módulos

Routes En Angular

Angular

Enrutado Y Navegación

Router En Angular

Angular

Enrutado Y Navegación

La Directiva Routerlink En Angular

Angular

Enrutado Y Navegación

Parámetros En Rutas Con Activatedroute

Angular

Enrutado Y Navegación

Routes Sin Módulos En Angular

Angular

Enrutado Y Navegación

Servicios En Angular

Angular

Servicios E Inyección De Dependencias

Httpclient En Servicios De Angular

Angular

Servicios E Inyección De Dependencias

Formularios Con Ngmodel En Angular

Angular

Formularios

Formularios Reactivos En Angular

Angular

Formularios

Subir Archivo En Formularios

Angular

Formularios

Layout Con Angular Material

Angular

Integración Con Angular Material

Tablas En Angular Material

Angular

Integración Con Angular Material

Formularios En Angular Material

Angular

Integración Con Angular Material

Instalación Y Uso De Ngboostrap

Angular

Integración Con Bootstrap Css

Signals En Angular

Angular

Signals Y Reactividad

Effects En Angular

Angular

Signals Y Reactividad

Route Guards Basados En Interfaces

Angular

Autenticación Y Autorización

Guards Funcionales

Angular

Autenticación Y Autorización

Interceptores Http Basados En Interfaz

Angular

Autenticación Y Autorización

Interceptores Http Funcionales

Angular

Autenticación Y Autorización

Seguridad Jwt En Angular

Angular

Autenticación Y Autorización

Decodificar Tokens Jwt En Angular

Angular

Autenticación Y Autorización

Certificados de superación de Angular

Supera todos los ejercicios de programación del curso de Angular y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Dominar componentes standalone en Angular.
  2. Comprender los beneficios de los componentes standalone.
  3. Implementar prácticas de desarrollo eficientes con componentes standalone.
  4. Integración avanzada de componentes standalone con servicios y routing de Angular.
  5. Optimización de la aplicación mediante componentes standalone.