Bem legal este exercicio!
Ele deixa bem claro que a diretiva só pode funcionar em <input>
do tipo “text” e para isso vc precisa especificar direto no seletor da diretiva, assim:
@Directive({ selector: 'input[type="text"][logoCC]' })
Para saber que bandeira aplicar, vc precisa saber sempre que o valor do <input>
muda e para isso vc vai precisar usar o decorator @HostListener()
, algo assim:
@HostListener('input', ['$event.target.value'])
valueChange(value: string): void {
// do something...
}
Dessa forma o método valueChange()
vai ser chamado sempre que o usuário digitar algo.
Olha como ficou a minha diretiva:
@Directive({ selector: 'input[type="text"][logoCC]' })
export class LogoCCDirective {
@HostListener('input', ['$event.target.value'])
valueChange(value: string): void {
this.renderer.removeAttribute(this.bandeira, 'data-bandeira');
if (value) {
if (value.startsWith('37')) {
this.renderer.setAttribute(this.bandeira, 'data-bandeira', 'brazilian-express');
} else if (value.startsWith('4')) {
this.renderer.setAttribute(this.bandeira, 'data-bandeira', 'vista');
} else if (value.startsWith('5')) {
this.renderer.setAttribute(this.bandeira, 'data-bandeira', 'blastercard');
}
}
}
private readonly bandeira: HTMLSpanElement;
constructor(private readonly renderer: Renderer2, elementRef: ElementRef<HTMLInputElement>) {
const el = elementRef.nativeElement;
const parent = renderer.parentNode(el);
this.bandeira = renderer.createElement('span') as HTMLElement;
renderer.addClass(this.bandeira, 'bandeira');
renderer.insertBefore(parent, this.bandeira, el);
}
}
E para colocar as bandeira, eu usei CSS. Este é o que tem no meu style.css
:
.bandeira {
width: 20px;
height: 20px;
display: inline-block;
vertical-align: middle;
background-color: yellow;
}
.bandeira[data-bandeira='brazilian-express'] {
background-color: red;
}
.bandeira[data-bandeira='vista'] {
background-color: blue;
}
.bandeira[data-bandeira='blastercard'] {
background-color: green;
}
Viu como eu usei a propriedade background-color
para diferenciar as bandeiras? Vc só vai precisar substituir pela background-image
e apontar o caminho certinho das imagens.
Eu experimentei com a última versão do Angular, 12.2.2.
Código TypeScript completo
import { Component, Directive, ElementRef, HostListener, NgModule, Renderer2 } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@Directive({ selector: 'input[type="text"][logoCC]' })
export class LogoCCDirective {
@HostListener('input', ['$event.target.value'])
valueChange(value: string): void {
this.renderer.removeAttribute(this.bandeira, 'data-bandeira');
if (value) {
if (value.startsWith('37')) {
this.renderer.setAttribute(this.bandeira, 'data-bandeira', 'brazilian-express');
} else if (value.startsWith('4')) {
this.renderer.setAttribute(this.bandeira, 'data-bandeira', 'vista');
} else if (value.startsWith('5')) {
this.renderer.setAttribute(this.bandeira, 'data-bandeira', 'blastercard');
}
}
}
private readonly bandeira: HTMLSpanElement;
constructor(private readonly renderer: Renderer2, elementRef: ElementRef<HTMLInputElement>) {
const el = elementRef.nativeElement;
const parent = renderer.parentNode(el);
this.bandeira = renderer.createElement('span') as HTMLElement;
renderer.addClass(this.bandeira, 'bandeira');
renderer.insertBefore(parent, this.bandeira, el);
}
}
@Component({
selector: 'app-root',
template: '<input type="text" logoCC />'
})
export class AppComponent {}
@NgModule({
declarations: [AppComponent, LogoCCDirective],
imports: [BrowserModule],
bootstrap: [AppComponent]
})
export class AppModule {}