Saltar al contenido

Construyendo una directiva de la costumbre

Hay muchos casos de uso en nuestra aplicación, en los que tenemos un requisito personalizado y tenemos que crear una directiva personalizada según nuestro requisito.

Angular tiene algunas APIs básicas que pueden ayudarnos a crear directivas personalizadas. Echemos primero un vistazo a la creación de una directiva de atributos personalizados.

Construyendo una directiva de la costumbre
Construyendo una directiva de la costumbre

Directivas de atributos personalizados

Digamos que tenemos un requisito en el que queremos que cualquier elemento sea estilizado de una manera particular (por ejemplo, con un color de resaltado de fondo y algún color de texto/primer plano). Podemos tener tal texto en múltiples lugares, así que podemos crear una directiva personalizada para el mismo y reutilizarlo en nuestra aplicación. Así que, esencialmente, queremos ser capaces de usar nuestra directiva como se indica a continuación:

1<divmyHighlight;
Para crear la directiva, podemos ejecutar el siguiente comando usando el CLI angular:

1ng generar la directiva myHighlight

El comando anterior actualizaría automáticamente la entrada en nuestro app.module.ts. Sin embargo, si creamos la directiva manualmente, tendremos que actualizarla en nuestro AppModule como se indica a continuación:

123456789101112131415importar{NgModule}de$0027@angular/núcleo$0027;importar{BrowserModule}de$0027@angular/plataforma-browser$0027;importar{AppComponent}de$0027./app.component$0027;importar{MyHighlightDirective}de$0027. /mihighlight.directive$0027;@NgModule({ importa:[BrowserModule], declaraciones:[AppComponent,MyHighlightDirective], bootstrap:[AppComponent]})exportclassAppModule{}

javascript

Lo anterior informaría a Angular sobre nuestra nueva directiva y así es como sabe a qué clase invocar cuando se encuentra con el selector en la plantilla.

Ahora empezaremos con el decorador. Así que, cualquier clase de directiva tiene que ser anotada usando un decorador @Directivo.

Vamos a crear una clase llamada "MyHighlightDirective" y luego usar el decorador @Directive para asociar nuestra clase con el atributo "myHighlight", como se muestra a continuación:

12345678importación{Directiva}de$0027@angular/núcleo$0027;//...//...//...@Directiva({ selector:"[myHighlight]"})clase de exportaciónMyHighlightDirectiva{}

javascript

Como pueden ver, marcamos la clase usando el decorador @Directivo y tenemos que importar la misma desde @angular/núcleo.

Además, el código que se muestra arriba es bastante similar a la forma en que escribimos un componente. Una de las diferencias que podemos ver es que nuestro selector está envuelto dentro de [].Esto se debe a que nuestro atributo selector internamente utiliza las mismas reglas de concordancia de CSS para hacer coincidir cualquier directiva o componente y asignarlo a cualquier elemento HTML.

Por lo tanto, si tenemos que seleccionar cualquier elemento en particular a través de CSS, sólo tenemos que escribir el nombre del elemento como por ejemplo div {color de fondo: $0027verde$0027}.Y por eso, en el selector del componente en la directiva @Componente, sólo especificamos el nombre del componente.

Si actualizamos el selector en nuestra directiva como se indica a continuación:

12345678importación{Directiva}de$0027@angular/núcleo$0027;//...//...//...@Directiva({ selector:".myHighlight"})clase de exportaciónMyHighlightDirectiva{}

javascript

Con la definición anterior, nuestra directiva se asociaría a cualquier elemento que tenga una clase "myHighlight" definida como:

1<div... Algunos textos a resaltar...
html

Por ahora, asociemos nuestra directiva a un elemento con el atributo "myHighlight".

Una vez que tengamos nuestro decorador añadido, el siguiente paso sería añadir un constructor a nuestra directiva, como se muestra a continuación:

1234567891011importar{Directiva}de$0027@angular/núcleo$0027;importar{ElementRef}de$0027@angular/núcleo$0027;//...//...//...@Directiva({ selector:"[myHighlight]"})exportclassMyHighlightDirectiva{constructor(privado elRef:ElementRef){}}

javascript

Con el código anterior, le decimos a Angular que inyecte una instancia de ElementRef en su constructor, siempre que se cree la directiva. Esto es en realidad a través de la inyección de dependencia.

ElementRef se utiliza para obtener acceso directo al elemento DOM en el que se encuentra nuestro atributo directivo.

Digamos que ahora queremos cambiar el color de fondo de este elemento a verde y el color de primer plano a azul. Para hacer eso, escribiremos el siguiente código:

12el.nativeElement.style.backgroundColor="verde";el.nativeElement.style.color="azul";

javascript

ElementRef es en realidad un envoltorio para nuestro elemento DOM real y accedemos al elemento DOM usando la propiedad nativaElement en él.

Escribiremos el código anterior dentro de nuestro método ngOnInit. Así que así es como nuestra clase directiva se vería ahora;

123456789101112131415import{Directiva}de$0027@angular/núcleo$0027;import{ElementRef}de$0027@angular/núcleo$0027;//...//...//... @Directiva({ selector:"[miHighlight]"})exportarclaseMiHighlightDirectiva{constructor(privado elRef:ElementRef){}ngOnInit(){esto.elRef.nativeElement.style.backgroundColor="verde";esto.elRef.nativeElement.style.color="azul";}}

javascript

El único problema con el estilo de uso de las directivas mencionadas es que esto supondría que nuestra aplicación siempre se ejecutaría en un navegador. Sin embargo, puede que no siempre sea así. Podemos hacer que nuestra aplicación se ejecute en un entorno diferente como en un dispositivo móvil nativo. Por lo tanto, Angular ha provisto una API que es independiente de la plataforma y podemos establecer propiedades en nuestros elementos usando Renderer.

Así es como nuestra clase se actualizaría si usamos el ayudante de Renderer:

123456789101112131415importar{Directiva}de$0027@angular/núcleo$0027;importar{Renderer}de$0027@angular/núcleo$0027;//...//...//...@Directiva({ selector:"[myHighlight]"})exportclassMyHighlightDirectiva{constructor(privado elRef:ElementRef,privado renderer:Renderer){}ngOnInit(){esto. renderer.setStyle(this.elRef.nativeElement,$0027background-color$0027,$0027green$0027);this.renderer.setStyle(this.elRef.nativeElement,$0027color$0027,$0027blue$0027);}}

javascript

El método "setStyle" tiene la siguiente firma:

1setStyle(element: any, style: string, value: any, flags?:RendererStyleFlags2):void

javascript

Por lo tanto, ahora estamos actualizando el estilo de nuestro elemento DOM (color de fondo y de primer plano) a través del "Renderizador" y no accediendo directamente a nuestro elemento, lo cual es una buena práctica.

Ahora estamos aplicando un código de colores de fondo y de primer plano al elemento DOM. Digamos que queremos que sea configurable, lo que significa que nuestro elemento DOM puede decir que necesita que el color de fondo y el color de primer plano sean algo específico. Por lo tanto, queremos ser capaces de decir:

1&lt;divmyHighlight[backgroundColor]="$0027negro$0027"[foregroundColor]="$0027blanco$0027"³Algún texto a resaltar !<;/div
html

Lo anterior se puede lograr con la ayuda del decorador @Input. También usaremos el decorador @HostBinding para actualizar los estilos de nuestro elemento. Actualicemos nuestra clase mostrando el uso de @Input y @HostBinding:

1234567891011121314151617181920importación{Directiva}de$0027@angular/núcleo$0027;importación{Entrada}de$0027@angular/núcleo$0027;importación{HostBinding}de$0027@angular/núcleo$0027;//...//...//... @Directiva({ selector:"[myHighlight]"})exportclassMiHighlightDirectiva{ @Input() backgroundColor:cadena =$0027verde$0027; @Input() foregroundColor:cadena =$0027azul$0027; @HostBinding($0027style. backgroundColor$0027) bgColor:cadena; @HostBinding($0027style.color$0027) color:cadena;constructor(){}ngOnInit(){this.bgColor=this.backgroundColor;this.color=this.foregroundColor;}}

javascript

Si ves el código anterior, ahora tenemos valores por defecto para los colores de fondo y de primer plano (es decir, verde y azul). Sin embargo, si los valores se pasan a la directiva a través de la vinculación de datos, en su lugar usamos esos valores para establecer los estilos en nuestro elemento.

También podemos adjuntar oyentes de eventos a nuestra directiva. Digamos que queremos que nuestro texto tenga un fondo y un color de primer plano diferentes cuando el usuario se mueve sobre él. Por lo tanto, queremos ser capaces de pasar esto a nuestra directiva:

12345&lt;divmyHighlight[backgroundColor]="$0027black$0027"[foregroundColor]="$0027white$0027"[hoverBackgroundColor]="$0027yellow$0027"[hoverForegroundColor]="$0027red$0027"=Algún texto a resaltar !

html

Para poder hacer esto, necesitaremos usar el decorador @HostListener como se muestra a continuación:

123456789101112131415161718192021222324252627importar{Directiva}de$0027@angular/núcleo$0027;importar{Ingreso}de$0027@angular/núcleo$0027;importar{HostBinding}de$0027@angular/núcleo$0027;importar{HostListener}de$0027@angular/núcleo$0027;//...//...//... @Directive({ selector:"[myHighlight]"})exportclassMiHighlightDirective{ @Input() backgroundColor:cadena =$0027verde$0027; @Input() foregroundColor:cadena =$0027azul$0027; @Input() hoverBackgroundColor:cadena =$0027gris$0027; @Input() hoverForegroundColor:cadena =$0027naranja$0027; @HostBinding($0027style. backgroundColor$0027) bgColor:cadena; @HostBinding($0027estilo.color$0027) color:cadena;constructor(){}ngOnInit(){este.bgColor=este.backgroundColor;este.color=este.foregroundColor;} @HostListener($0027mouseenter$0027)onMouseEnter(eventData:Event){this.bgColor=this.hoverBackgroundColor;this.color=this.hoverForegroundColor;}}

javascript

Por lo tanto, los oyentes anfitriones son sólo oyentes de eventos que se unen al elemento DOM que alberga nuestra directiva.

Directiva estructural personalizada

Ahora que entendemos la directiva de atributos personalizados, echemos un vistazo rápido a cómo podemos crear una directiva estructural personalizada. Podemos intentar recrear la directiva ngIf incorporada. Llamémosla "miCustomIf". Así es como se vería la clase para eso:

1234567891011121314151617181920212223import{Directiva}de$0027@angular/núcleo$0027;import{Input,TemplateRef,ViewContainerRef}de$0027@angular/núcleo$0027;@Directiva({ selector: $0027[miCustomIf]$0027})exportclassmyCustomIfDirective{constructor(plantilla privada:TemplateRef&lt;any};,contenedor privado:ViewContainerRef){} @Input()setmyIf(shouldAddToDOM: boolean){if(shouldAddToDOM){// Si el valor es verdadero, agregue la plantilla al DOMthis.container.createEmbeddedView(this.template);}else{// De lo contrario, elimine la plantilla del DOMthis.container.clear();}}}

javascript

Ahora podemos usar esta directiva en cualquier parte de nuestra aplicación. Para ello, simplemente escribiremos;

1234&lt;!-- /app/my.component.html --;<;div*myCustomIf="false "*; Inside if&lt;/div;

html