Angular: T4- Directivas -- Estructurales y Atributo

 ¿Qué son las Directivas?

Directivas en Angular (Built-in directives): https://angular.dev/guide/directives

Las directivas en Angular son instrucciones en el DOM (Document Object Model) que le dicen al Angular cómo transformar o manipular elementos del DOM. Existen tres tipos principales de directivas:

  1. Directivas Estructurales: Cambian la estructura del DOM (añadir, eliminar, o modificar elementos). Ejemplo: @If, @For, *ngIf, *ngFor, *ngSwitch, *ngSwitchCase, *ngSwitchDefault
  2. Directivas Atributo: Cambian el aspecto o comportamiento de un elemento, componente o directiva existente. Ejemplo: ngClass, ngStyle, ngModel.
  3. Directivas Componentes: Son directivas con una plantilla asociada. En Angular, todos los componentes son directivas.

Video tutoriales: 

  1. Angular (v18) Controles de Flujo (@If, @For) y Manejo de Eventos: https://youtu.be/g72m_ThgojE
  2. Directivas en Angular: https://youtu.be/PPvprSz77jk
  3. Curso Angular 2023 #4 Directivas y Pipes En Angular: https://youtu.be/FEPqtxyThU0
  4. Directiva: ngIf, ngFor    https://youtu.be/ZUX_K4jR-9Q?list=PL_9MDdjVuFjFBed4Eor5qj1T0LLahl4z0
  5.  Angular 17: Part #3 ngSwitch   https://youtu.be/Dd9kVq3wmZ8
  6. Directiva: ngClass, ngStyle   https://youtu.be/9ZExEHDREeQ
  7. ANGULAR: DIRECTIVAS ESTRUCTÚRALES / ATRIBUTOS, NG - CONTAINER / TEMPLATE: https://youtu.be/On_Bn6Rqyks 
  8. Crear variables en Angular https://codingpotions.com/angular-vistas-bindings/
  9. Ciclo de vida componente Angular: https://youtu.be/8lHdqC1GDGs

1- Directivas Estructurales:

Directivas Estructurales Cambian la estructura del DOM (añadir, eliminar, o modificar elementos). Ejemplo: @If, @For,  *ngIf, *ngFor, *ngSwitch, *ngSwitchCase, *ngSwitchDefault

@If

@If, @If-@else: Renderiza un elemento del DOM si la condición es verdadera. No necesita uso del modulo: commonModule, para poder usarse

import { Component } from '@angular/core';

@Component({
  selector: 'app-flujo',
  standalone: true,
  imports: [],
  template:`
      @if (esadmin == true) {
     <h4>Usuario admin Autenticado</h4>
    }@else {
      <h4>No eres Usuario adminlt;</h4>
    }
    
  `,
  styleUrl: './flujo.component.css'
})
export class FlujoComponent {
 esadmin:boolean = false;
}

*ngIf

*ngIf: Renderiza un elemento del DOM si la condición es verdadera. Necesita uso del modulo: commonModule, para poder usarse (   import { CommonModule } from '@angular/common';   )

// ng-if.component.ts
import { Component } from '@angular/core';
// Agregando para usar directivas ng-if, ngfor,
import { CommonModule } from '@angular/common'; 

@Component({
  selector: 'app-ng-if',
  standalone: true,
  imports: [CommonModule],
  template: `
<h3>ng-if </h3> 
<div *ngIf="isLoggedIn">Welcome, user!</div>
<button (click)="toggleLogin()">Toggle Login</button>
  `,
  styles: [`h3 { color: green; }`]
})
export class NgIfComponent {
  isLoggedIn = false;
  toggleLogin() {
    this.isLoggedIn = !this.isLoggedIn;
  }
}

@for

@for No necesita uso del modulo: commonModule, para poder usarse.

import { Component } from '@angular/core';
// @for. Se refiere a cada uno de los miembros de la matriz

@Component({
    selector: 'app-cliente',
    standalone: true,
    template: `
      <div> <!-- Listando Matriz Uno -->
      <ul> <!-- cliente = variable de almacenamiento temporal -->
      	@for (cliente of clientes; track cliente) {
        <li>{{ cliente.name }}</li>
        }
     </ul>
    `,
  })
  export class ClienteComponent {
    // Matriz Uno
    clientes = [{name: 'Carlos'}, {name: 'Elmer'}, {name: 'Jose'}];
    cliente = 'Rocha';
  }

@for con selección multiple. No necesita uso del modulo: commonModule, para poder usarse. 


import { Component } from '@angular/core';

@Component({
  selector: 'app-flujo',
  standalone: true,
  imports: [],
  template:`
      <ol>
      	@for (ciudad of ciudades; track ciudad.id)
{ <li>{{ciudad.nombre}}</li> }
</ol>
<select> @for (ciudad of ciudades; track ciudad.id)
{ <option>{{ciudad.nombre}}</option> }
</select> <p> {{mensaje}} </p> `, styleUrl: './flujo.component.css' }) export class FlujoComponent { ciudades= [{id:'1', nombre:'La paz'}, {id:'2', nombre:'Mexico'}, {id:'3', nombre:'Jalisco'}, {id:'4', nombre:'Moterrey'}, ] mensaje=''; guardar(){ this.mensaje = 'Datos Guardados'; } } // ** Nota: // ciudad seria la variable a usar como clave primaria e ID. // track seria el id (llave) de cada objeto del array

Aquí va el código Javascript a mostrar en la entrada.

...

*ngFor

*ngFor: Renderiza un elemento del DOM por cada elemento en una colección. Necesita uso del modulo: commonModule, para poder usarse (   import { CommonModule } from '@angular/common';   )

//  ng-for.component.ts
import { Component } from '@angular/core';
// Agregando para usar directivas ng-if, ngfor,
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-ng-for',
  standalone: true,
  imports: [CommonModule, ],
  template: `
<h3>ng-for </h3>
<ul>   <!-- "let = item" variable de almacenamiento temporal -->
	 <li *ngFor="let item of items">{{ item }}</li>
</ul>
  `,
  styles: [`h3 { color: red; }`]
})
export class NgForComponent {
items = ['Item 1', 'Item 2', 'Item 3'];
}


*ngSwitch

*ngSwitch, *ngSwitchCase, *ngSwitchDefault: Condicionalmente incluye una plantilla basada en una expresión de cambio. Necesita uso del modulo: commonModule, para poder usarse (   import { CommonModule } from '@angular/common';   )

 // ng-switch.component.ts
import { Component } from '@angular/core';
// Agregando para usar directivas ng-if, ngfor,
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-ng-switch',
  standalone: true,
  imports: [CommonModule,],
  template: `
    <h3>ng-switch</h3>
<div [ngSwitch]="viewMode">
<ng-template ngSwitchCase="map">Map View</ng-template>
<ng-template ngSwitchCase="list">List View</ng-template>
<ng-template ngSwitchDefault>Other View</ng-template>
</div>
<button (click)="changeView('map')">Map</button>
<button (click)="changeView('list')">List</button>
<button (click)="changeView('other')">Other</button> `, styles: [`h3 { color: blue; }`] }) export class NgSwitchComponent { viewMode = 'map'; changeView(mode: string) { this.viewMode = mode; } }


import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';

@Component({
    selector: 'app-ejemplo2', standalone: true,
    imports: [CommonModule],
    template:`
        <input type="text" class="from-control" #newDay>
        <button class="btn btn-primary mt-2 mb-4" (click)="dia= newDay.value">
        Mostrar dia
        </button>
        <div [ngSwitch]="dia" *ngIf="dia">
        <p *ngSwitchCase="'1'"> Lunes  </p>
        <p *ngSwitchCase="'2'"> Martes </p>
        <p *ngSwitchCase="'3'"> Miercoles </p>
        <p *ngSwitchCase="'4'"> Jueves </p>
        <p *ngSwitchCase="'5'"> Viernes </p>
        <p *ngSwitchCase="'6'"> Sabado </p>
        <p *ngSwitchCase="'7'"> Domingo </p>
        <p *ngSwitchDefault> No aplica  </p>
        </div>
    `,
    styles:`[]`
})
export class Ejemplo2Component {
    dia?:string;
  }


2- Directivas Atributo:

Directivas Atributo: Cambian el aspecto o comportamiento de un elemento, componente o directiva existente. Ejemplo: ngClass, ngStyle.

ngClass

: Añade o elimina clases CSS

import { Component } from '@angular/core';
// Agregando para usar directivas ng-if, ngfor, ngClass
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-ng-class',
  standalone: true,
  imports: [CommonModule],
  template: `
     <h3> ng-class </h3>
	<div [ngClass]="{'active': isActive, 'disabled': isDisabled}">Content</div>
    <button (click)="toggleActive()">Toggle Active</button>
<button (click)="toggleDisabled()">Toggle Disabled</button> `, styles: [`h3 { color: green; }`] }) export class NgClassComponent { isActive = false; isDisabled = false; toggleActive() { this.isActive = !this.isActive; } toggleDisabled() { this.isDisabled = !this.isDisabled; } }

ngStyle

ngStyle: Aplica, Añade y elimina estilos en línea.

import { Component } from '@angular/core';
// Agregando para usar directivas ngif, ngfor, ngstyle
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-ng-style',
  standalone: true,
  imports: [CommonModule, ],
  template: `
    <h3> ng-style </h3>
	<div [ngStyle]="{'color': textColor, 'font-size': fontSize}">Styled Content</div>
    <button (click)="changeStyle()">Change Style</button>
  `,
  styles: [`h3 { color: purple; }`]
})
export class NgStyleComponent {
  textColor = 'blue';
  fontSize = 14;
  changeStyle() {
    this.textColor = this.textColor === 'blue' ? 'red' : 'blue';
    this.fontSize = this.fontSize === 14 ? 20 : 14;
  }
}

ngModel: Enlaza una propiedad de un elemento de formulario a una propiedad de datos.


import { Component } from '@angular/core';
// Agregando FormsModule para usar directivas ng-model
import { FormsModule  } from '@angular/forms';

@Component({
  selector: 'app-ng-model',
  standalone: true,
  imports: [ FormsModule],
  template: `
    <h3> ng-model </h3>
<input [(ngModel)]="name" placeholder="Enter your name">
<p>Hello, {{ name }}!</p> `, styles: [`h3 { color: brown; }`] }) export class NgModelComponent { name = ''; }


3- Directivas Componentes:

Directivas Componentes: Son una forma especializada de directiva con una plantilla asociada. En Angular, todos los componentes son directivas.

C:\ANGULAR-v18\Cmder_Consola 
// Creando nuevo proyecto APP= practica2
 ng new practica2
                                    
 cd practica2         // Entrando a la carpeta del proyecto
 
C:\ANGULAR-v18\Cmder_Consola\practica2 (master)                 
 code .  		// Abriendo el proyecto en la visual estudio code
 
// Generando componentes 
ng g c modulo-comun 
// Generando componentes en carpeta Directives
ng g c modulo-comun/directives 
 
// Generando componente --inline-template 
ng generate component --inline-template modulo-comun/directives/ng-if
 
// Generando componente --inline-template --inline-style
ng g c --inline-template --inline-style modulo-comun/directives/ng-for

ng g c --inline-template --inline-style modulo-comun/directives/ng-switch

ng g c --inline-template --inline-style modulo-comun/directives/ng-class

ng g c --inline-template --inline-style modulo-comun/directives/ng-style

ng g c --inline-template --inline-style modulo-comun/directives/ng-model

// Abriendo el servidor y el navegador web
ng serve --open
 

directives.component.ts

 // directives.component.ts
import { Component } from '@angular/core';
// Agregando los componentes creados de cada directiva
import { NgIfComponent } from './ng-if/ng-if.component';
import { NgForComponent } from './ng-for/ng-for.component';
import {NgSwitchComponent} from './ng-switch/ng-switch.component';
import {NgClassComponent} from './ng-class/ng-class.component';
import {NgStyleComponent} from './ng-style/ng-style.component';
import {NgModelComponent} from './ng-model/ng-model.component'

@Component({
  selector: 'app-directives',
  standalone: true,
  // Declaramos o confirmamos que hemos agregando los componentes
  imports: [NgIfComponent, NgForComponent, NgSwitchComponent,
  			NgClassComponent, NgStyleComponent, NgModelComponent, ],
  template: `
    <h2>Directivas</h2>
<app-ng-if/>
<app-ng-for/>
<app-ng-switch/>
<app-ng-class/>
<app-ng-style/>
<app-ng-model/> `, styleUrl: './directives.component.css' }) export class DirectivesComponent { }

modulo-comun.component.ts

// modulo-comun.component.ts
import { Component } from '@angular/core';
// Agregando los componentes creados en directives
import { DirectivesComponent } from './directives/directives.component'

@Component({
  selector: 'app-modulo-comun',
  standalone: true,
  // Declaramos o confirmamos que hemos agregando el componente
  imports: [DirectivesComponent, ],
  template: `
    <h2>modulo-comun</h2>
<app-directives/> `, styleUrl: './modulo-comun.component.css' }) export class ModuloComunComponent { }

 4- Directivas Personalizadas: Directivas definidas por el usuario para agregar comportamientos específicos



 

APP: Estructura de un Proyecto Angular con Directivas y Pipes


practicaDirectiva/
├── src/
│   ├── app/
│   │   ├── directives/
│   │   │   └── highlight.directive.ts
│   │   ├── pipes/
│   │   │   └── exponential-strength.pipe.ts
│   │   ├── app.component.ts
│   │   ├── app.component.html
│   │   ├── app.component.css
│   │   └── app.module.ts
│   ├── assets/
│   ├── environments/
│   ├── index.html
│   ├── main.ts
│   └── styles.css
├── angular.json
├── package.json
├── tsconfig.json
└── tslint.json

 

Construcción de una APP con Directivas y Pipes

1- Instalar Angular CLI:

 npm install -g @angular/cli

2- Crear un Nuevo Proyecto:

 ng new practicaDirectiva
  cd practicaDirectiva

3- Generar una Directiva:

 ng generate directive directives/highlight

4- Generar un Pipe:

 ng generate pipe pipes/exponentialStrength 

5- Agregar Lógica en la Directiva y el Pipe:
Editar highlight.directive.ts como se muestra arriba.


import { Directive, ElementRef, Renderer2, HostListener } from '@angular/core';

@Directive({
  selector: '[appHighlight]',
  standalone: true
})
export class HighlightDirective {

  constructor(private el: ElementRef, private renderer: Renderer2) { }

  @HostListener('mouseenter') onMouseEnter() {
      this.renderer.setStyle(this.el.nativeElement, 'backgroundColor', 'yellow');
    }

    @HostListener('mouseleave') onMouseLeave() {
      this.renderer.setStyle(this.el.nativeElement, 'backgroundColor', 'red');
    }
}


Editar exponential-strength.pipe.ts como se muestra arriba.


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'exponentialStrength',
  standalone: true
})
export class ExponentialStrengthPipe implements PipeTransform {
  transform(value: number, exponent: string): number {
    let exp = parseFloat(exponent);
    return Math.pow(value, isNaN(exp) ? 1 : exp);
  }
}

6- Actualizar el Módulo Principal:
Asegurarse de que HighlightDirective y ExponentialStrengthPipe estén importados y declarados en app.component.ts.


import { Component } from '@angular/core';

// Directivas importadas
import { HighlightDirective } from './directives/highlight.directive';
// Pipes importado
import { ExponentialStrengthPipe } from './pipes/exponential-strength.pipe';


@Component({
  selector: 'app-root',
  standalone: true,
  // Declarando modulos importados o Agregados
  imports: [HighlightDirective, ExponentialStrengthPipe, ],
  templateUrl: './prueba-ejemplo.component.html',
  styleUrl: './prueba-ejemplo.component.css'
})
export class AppComponent {

}

7- Actualizar el Componente Principal:
Editar app.component.html para usar la directiva y el pipe como se muestra arriba.




<h2>Directivas y Pipes</h2>
<div>
<h4 appHighlight> Directivas Highlight me!</h4>
<br>
<p>Trabajando con Pipes; The exponent of 3^2 is: {{ 3 | exponentialStrength: '2' }} </p>
</div>

 

8- Iniciar la Aplicación: bash

 ng serve --open 

Navegar a http://localhost:4200 para ver la aplicación en funcionamiento.
 

Librerías Utilizadas
Angular Core: @angular/core para la funcionalidad básica.
Angular Platform Browser: @angular/platform-browser para la integración con el navegador.

....