Envolvemos uma janela de confirmação modal Promise

Quando o usuário executa algumas ações críticas e / ou irreversíveis, antes de enviar uma solicitação ao servidor, você precisa pedir uma confirmação ao usuário.

Como regra, o modal "Você tem certeza de que deseja fazer isso e aquilo e aquilo" é exibido e há dois botões abaixo: Sim e Não. Se o usuário clicou em "yes", enviamos uma solicitação ao servidor e fechamos o modal. Caso contrário, basta fechar o modal.

Essa é a funcionalidade padrão comumente usada em vários locais de um projeto. Além disso, ao desenvolver a funcionalidade do projeto, é provável que você adicione mais alguns lugares onde os modais com confirmação são necessários. Portanto, para evitar a duplicação de código, esse tipo de modalidade deve ser inequivocamente inequívoco em um componente separado. Para evitar a tentação de martelar muletas, esse componente deve ser o mais versátil e fácil de usar possível.

Vamos passar da letra para a ação. Para exibir o modal, usaremos o Bootstrap.

Na verdade, minha versão desse componente:

yes-no-modal.component.html
<div bsModal #yesNoModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog modal-{{type}}" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">{{title}}</h4>
        <button type="button" class="close" (click)="onNoClick()" aria-label="Close">
          <span aria-hidden="true">×</span>
        </button>
      </div>
      <div class="modal-body">
        <p>{{body}}</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" (click)="onNoClick()">{{noBtnText}}</button>
        <button type="button" class="btn btn-{{type}}" (click)="onYesClick()">{{yesBtnText}}</button>
      </div>
    </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div><!-- /.modal -->

yes-no-modal.component.ts
import {Component, Input, OnInit, ViewChild} from '@angular/core';
import {ModalDirective} from 'ngx-bootstrap/modal';

@Component({
  selector: 'app-yes-no-modal',
  templateUrl: './yes-no-modal.component.html',
  styleUrls: ['./yes-no-modal.component.css']
})
export class YesNoModalComponent implements OnInit {

  @ViewChild('yesNoModal') public yesNoModal: ModalDirective;

  @Input() private type = 'info';
  @Input() private title = '';
  @Input() private body = '';
  @Input() private yesBtnText = '';
  @Input() private noBtnText = '';

  constructor() { }

  ngOnInit(): void {
  }

  public showAsync(data = null): Promise<any> {
    return new Promise<any>((resolve, reject) => {
      this.yesNoModal.show();
      this.onYesClick = () => {
        this.yesNoModal.hide();
        resolve(data);
      };
      this.onNoClick = () => {
        this.yesNoModal.hide();
        reject(data);
      };
    });
  }

  private onYesClick(): any {}
  private onNoClick(): any {}

}

Coloquei o cabeçalho de aviso, o texto de aviso, o esquema de cores / nível de importância (perigo, informações, aviso) nos parâmetros, você também pode redefinir o rótulo nos botões.

Para mostrar o modal, chame showAsync, para o qual podemos transferir dados arbitrários. Obtemos os mesmos dados em resolver / rejeitar.

Em seguida, conecte o modal em outro componente:

account.component.html
<app-yes-no-modal
  #deleteModal
  body="     ?"
  title=""
  type="danger"
></app-yes-no-modal>
<button (click)="delete()"></button>

account.component.ts
import {Component, OnInit, ViewChild} from '@angular/core';
import {YesNoModalComponent} from '../_common/yes-no-modal/yes-no-modal.component';
import {DeleteUserEndpoint} from '../../api/delete-user.endpoint';
import {ErrorService} from '../../services/error/error.service';

@Component({
  selector: 'app-account',
  templateUrl: './account.component.html',
  styleUrls: ['./account.component.css'],
  providers: [DeleteUserEndpoint]
})
export class AccountComponent implements OnInit {


  @ViewChild('deleteModal') public deleteModal: YesNoModalComponent;

  constructor (private deleteUserEndpoint: DeleteUserEndpoint) {
  }

  delete(data) {
    this.deleteModal.showAsync(data).then(result => {
      this.deleteUserEndpoint.execute(result);
    });
  }

  ngOnInit(): void {
  }
}

Na minha opinião, o uso de uma solução desse tipo parece o mais simples e legível possível.

Para comparação, ao usar EventEmitter, você terá que definir dois métodos em cada componente - showDeleteModal (), chamado ao clicar no botão excluir, e o método delete (), chamado pelo evento modal. Se você tiver vários desses modais em um componente para diferentes ações do usuário, a legibilidade do código já será prejudicada.

Nos comentários, como sempre, espero críticas construtivas e razoáveis.

All Articles