Preciso de ajuda com essa atividade de Angular por favor

Bom dia! Pessoal, preciso escrever esse código para a atividade abaixo, mas estou com dificuldades. Podem me ajudar por favor? Agradeço desde já!

Desenvolver aplicações em Angular envolve conhecer vários assuntos, como, por exemplo, mostrar dados, criar entradas de dados interativos com o usuário, trabalhar com estilos e aplicar em páginas HTML para torná-las mais interativas e usáveis. Uma dessas formas é criar diretivas e aplicá-las em elementos HTML.

Por meio de diretivas, e um pouco de pesquisa na documentação do Angular, é possível customizar uma caixa de entrada ( input ) em HTML, de forma que à medida que o usuário digitar um número de cartão de crédito,a diretiva mostre uma imagem da bandeira Blastercard, Vista ou Brazilian Express, dependendo da entrada de dados. O seu Desafio é criar essa diretiva e aplicá-la em um formulário de entrada de dados.

Desenvolva um pequeno script contendo uma diretiva chamada “logoCC” para customizar uma entrada de dados do tipo texto ( input type=“text” ) de acordo com o que foi especificado.

Para resolver o Desafio, você vai precisar de algumas dicas:

– Os cartões da American Express sempre começam com 37.
– Os cartões da Visa começam sempre com o número 4.
– Os cartões da Mastercard sempre começam com 5.

Para padronizar, salve as imagens em uma pasta dentro da pasta do seu projeto no seguinte path : “my-app\src\assets\img”. Cada bandeira de cartão de crédito tem uma imagem diferente.

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 {}
2 curtidas

@wldomiciano

Muito bom. Angular é bacana msm. Pena que onde trabalho o pessoal só usa vue e react (povo não curte muito o angular lá não).

Pergunta, supondo que as bandeiras sejam tratadas por um componente à parte, será que teria como fazer algum tipo de integração (comunicação) entre a diretiva e esse outro componente?

Teria que ver como é o cenário exatamente. Se eu entendi bem o seu caso, vc não precisaria criar uma diretiva e a comunicação seria feita através de um @Input(). Eu fiz um exemplo:

import { Component, Input, NgModule } from '@angular/core';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';

@Component({
  selector: 'app-bandeira',
  styles: [
    `
      span {
        width: 20px;
        height: 20px;
        display: inline-block;
        vertical-align: middle;
        background-color: yellow;
      }

      span[data-bandeira='brazilian-express'] {
        background-color: red;
      }

      span[data-bandeira='vista'] {
        background-color: blue;
      }

      span[data-bandeira='blastercard'] {
        background-color: green;
      }
    `
  ],
  template: `<span [attr.data-bandeira]="bandeira"></span>`
})
export class BandeiraComponent {
  bandeira?: string;

  @Input()
  set value(v: any) {
    this.bandeira = '';

    if (v) {
      if (v.startsWith('37')) {
        this.bandeira = 'brazilian-express';
      } else if (v.startsWith('4')) {
        this.bandeira = 'vista';
      } else if (v.startsWith('5')) {
        this.bandeira = 'blastercard';
      }
    }
  }
}

@Component({
  selector: 'app-root',
  template: `
    <!-- Só com recursos do input -->
    <app-bandeira [value]="value"></app-bandeira>
    <input (input)="onInput($event.target)" type="text" />

    <br />

    <!-- Usando reactive form -->
    <app-bandeira [value]="control.value"></app-bandeira>
    <input type="text" [formControl]="control" />
  `
})
export class AppComponent {
  readonly control = new FormControl();

  value?: string;

  onInput(target: EventTarget | null) {
    this.value = (target as HTMLInputElement)?.value;
  }
}

@NgModule({
  declarations: [AppComponent, BandeiraComponent],
  imports: [BrowserModule, ReactiveFormsModule],
  bootstrap: [AppComponent]
})
export class AppModule {}
1 curtida

Não fui eu quem fiquei com dúvida hehe. Só perguntei por curiosidade msm pq acho o angular muito massa, mas nunca mais usei ele.

2 curtidas

Muito obrigado pela ajuda! A faculdade passou essa atividade, mas no capítulo do livro que eles disponibilizaram e nos slides, não tem nada sobre isso! Procurei na internet e nada também! Hoje tem aula online as 19h, vou ver se consigo mais informações! Mas, mais uma vez, agradeço a ajuda!

Jah Bless

@diegoetep2019 Apenas para referência, segue link da documentação do angular sobre diretivas:

No menu lateral tem Attribute Directives e Structural Directives

Com o código que o @wldomiciano passou junto com uma lida nessa documentação, vc conseguirá resolver seu exercício de forma bem mais tranquila.

Valeu!!

Como faço para rodar seu TypeScript, não consegui, poderia me ajudar?

Adiciona a classe que eu mostrei em qualquer projeto Angular, declara ela no NgModule apropriado e pronto, a diretiva está pronta para ser usada.