Directivas
En angular tenemos 3 tipos de directivas:
- Directivas de componente → Son los componentes que hemos visto. Tienen asociada una plantilla que se inserta dentro del elemento que coincide con el selector (misma sintáxis que en CSS) definido en el decorador @Component. La plantilla es gestionada por la clase del componente.
- Directivas de atributo → Se le añaden a elementos existentes, pueden ser elementos HTML estándar o componentes. En este caso son clases que añaden funcionalidad y cierto comportamiento a dichos elementos. El contrario que los componentes, aquí no hay plantilla asociada.
- Directivas estructurales → Se le añaden a elementos que queremos controlar cuando se añaden y se quitan del DOM. Las directivas de Angular *ngIf, *ngFor y *ngSwitch, son estructurales. Como han sido sustituidas por la nueva sintaxis de Angular 17 (aunque siguen funcionando), y es raro crear nuestras propias directivas estructurales, no las vamos a ver en este curso.
Directivas de atributo
Las directivas ngClass y ngStyle son ejemplos de directivas de atributo, ya que se les pueden poner a cualquier elemento del DOM y gestionan las clases y estilos CSS internos de dicho elemento.
Se pueden crear nuevas directivas de atributo con el comando ng generate directive (o ng g d). Las directivas son clases que tienen el decorador @Directive.
Vamos a hacer un ejemplo simple creando una directiva que al asignársela a un elemento, cuando hagamos clic en dicho elemento, le cambie el color de fondo:
ng g d directives/set-color
Cuando un elemento (cuyo componente haya importado la directiva), se le añada el atributo setColor, se le asociará un objeto de la clase setColorDirective que permitirá manipular atributos, eventos, etc de dicho elemento. Como podemos observar, el selector está entre corchetes, lo que implica que es un atributo añadido a cualquier elemento. Podríamos ser más específicos, por ejemplo, limitando solo a inputs con el selector input[setColor].
El atributo setColor, además podrá tener un valor asociado (el color elegido), que recibiremos con un parámetro de entrada @Input (como en los componentes). Por ahora, inyectaremos ElementRef (veremos como funciona la inyección de dependencias más adelante) para poder acceder al elemento que contiene la directiva y cambiarle el color de fondo.
Para usar la directiva en la plantilla de un componente, debemos importar su clase primero en el array imports del componente. Después, le ponemos el atributo marcado por el selector de la directiva y el valor del color.
Se considera una mejor práctica utilizar el decorador @HostBinding, que permite vincular atributos del elemento que contiene la directiva a una propiedad de la clase. De esa manera ya no necesitamos inyectar ElementRef para acceder al elemento nativo en el DOM.
Ahora vamos a hacer que el color pueda cambiar en cualquier momento. Para eso, en el componente, que contiene el elemento con la directiva, vamos a crear una propiedad (color), que vamos a vincular con ngModel a una lista desplegable. Para vincular el valor de setColor a dicha propiedad, usaremos la notación de corchetes.
Para que cuando cambie el color, se actualice el color de fondo, lo que vamos a hacer es detectar los cambios de la propiedad @Input de la directiva. Podemos hacer eso con el método ngOnChanges (funciona como el ciclo de vida de los componentes), o creando un setter asociado a la propiedad @Input, de tal forma que cuando cambie su valor, actualicemos el color de fondo del elemento (y podemos quitar ngOnInit).
Por último, para vincular eventos del elemento que contiene a la directiva, usaremos el decorador @HostListener junto a un método que se llamará cuando ocurra dicho evento. Como ejemplo, vamos a hacer que el color del texto cambie entre negro y blanco cada vez que hagamos clic en el elemento.