Blazor - CRUD com EF Core e Modals (NET 6) - III
 Neste post vamos iniciar uma série de tutoriais para mostrar como criar uma aplicação Blazor Server e realizar o CRUD usando o EF Core e outros recursos no ambiente do  .NET 6.


Continuando o artigo anterior vamos agora implementar a edição e a exclusão de tarefas.
...
 


 


Editando tarefas


Vamos ver como reutilizar o componente filho e o serviço TarefaService para editar um registro existente.

Primeiro, precisamos conectar o botão “Editar” para abrir o componente filho TarefaDetalhes.razor. Ele também precisa passar os detalhes da tarefa selecionada para o componente filho. Vamos modificar o botão de edição para abrir a janela modal e chamar um método para definir o objeto selecionado.

 

Alterando o componente Tarefas.razor :

 

...
@
foreach (var tarefa in tarefas)
{
 
<tr><td>@tarefa.Nome</td>
  <
td>@tarefa.Status</td>
  <
td>@tarefa.ConclusaoEm.ToShortDateString()</td>
   <
td><input type="button" class="btn btn-primary" @onclick="(() =>
       PreparaEdicao(tarefa))
" data-   toggle="modal" data-target="#tarefaModal"
      
value="Edita" /></td
>
   <
td><input type="button" class="btn btn-danger" value="Deleta" /></td>
   <
td><input type="button" class="btn btn-primary" value="Edita" /></td>
   <
td><input type="button" class="btn btn-danger" value="Deleta" /></td>
  </
tr>
}

@code {
   ...   

    private void PreparaEdicao(Tarefa tarefa)
    {
        cabecalho = "Edita Tarefa";
        tarefaObject = tarefa;
    }

   ...
}

No componente incluimos o evento onClick no botão e acionamos o método PreparaEdicao() definindo o cabeçalho e passando a tarefa a ser alterada.

As validações que implementamos para adicionar uma nova tarefa funcionarão automaticamente, pois também estamos usando o mesmo componente filho para Editar. Uma vez que o usuário modificou os dados e clicar em Salvar, o método HandleValidSubmit será acionado.

Assim temos que distinguir entre um novo registro e um registro existente para fazer a chamada de serviço apropriada. Vamos usar a propriedade Id para diferenciar os registros para inclusão e para edição incluindo no método HandleValidSubmit do componente TarefaDetalhes.razor código abaixo:

@code {
       ...

     private async void HandleValidSubmit()
     {
        
if (TarefaObj.Id == 0)
         {
           
await service.Add(TarefaObj);
         }
        
else
         {
            
await service.Update(TarefaObj);
         }
         
await CloseTarefaModal();
          AlteracaoDados?.Invoke();
     }

}
...

Renderizar Fragmentos – Conteúdo Dinâmico

A partir de agora, não há diferença entre as caixas de diálogo Adicionar e Editar. As legendas e os controles em ambos os diálogos são os mesmos que estamos retomando o diálogo.

O próximo requisito é mostrar alguma diferença visual entre os diálogos, mas a reutilização do componente filho deve continuar; para isso vamos usar um Render Fragment.

Um Render Fragment ou fragmento de renderização representa um segmento da interface do usuário a ser renderizado. Podemos passar conteúdo dinâmico dentro de elementos de tag de componente e pode ser renderizado em componentes filho usando a propriedade RenderFragment.

Primeiro, declare a propriedade RenderFragement no componente filho e substitua o título da caixa de diálogo modal pela propriedade.

Assim vamos alterar o componente TarefaDetalhes.razor conforme abaixo:

@inject ITarefaService service;
@inject IJSRuntime js;

<div class="modal" tabindex="-1" role="dialog" id="tarefaModal">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">@Cabecalho</h5>
 ...

@code {
    [Parameter]
    public Tarefa TarefaObj { get; set; }

    [Parameter]
    public RenderFragment Cabecalho { get; set; }

   ...

}

Agora no componente pai, passamos o conteúdo dinâmico dentro das tags do componente filho. O valor do conteúdo dinâmico é definido nos métodos add e edit. Passamos apenas o texto interno como um fragmento aqui, você pode passar um elemento HTML ou um elemento HTML aninhado.

...

<TarefaDetalhes TarefaObj=tarefaObject AlteracaoDados="@AlteracaoDados">
    <Cabecalho>@cabecalho</Cabecalho>
</TarefaDetalhes>

@code {
    List<Tarefa> tarefas;
    Tarefa tarefaObject = new Tarefa();
    string cabecalho = string.Empty;

    protected override async Task OnInitializedAsync()
    {
        tarefas = await service.Get();
    }

    private void PreparaEdicao(Tarefa tarefa)
    {
        cabecalho = "Edita Tarefa";
        tarefaObject = tarefa;
    }

    private void InitializeTarefaObject()
    {
        tarefaObject = new Tarefa();
        tarefaObject.ConclusaoEm = DateTime.Now;
        cabecalho = "Nova Tarefa";
    }

    private async void AlteracaoDados()
    {
        tarefas = await service.Get();
        StateHasChanged();
    }

}

Com isso teremos cabeçalhos distintos nas janelas modais para editar e incluir tarefa :

Deletar uma tarefa

Implementamos funcionalidades de adicionar e editar com validação. Vamos começar a trabalhar na exclusão agora.

Embora não possamos reutilizar o componente filho que já criamos, ainda podemos usar os recursos do JavaScript Interop.

Primeiro, precisamos conectar o botão de exclusão com algum evento. Esse evento definirá o objeto tarefa selecionado e passará as informações para o componente filho. Após a confirmação do componente filho para exclusão, precisamos excluir o registro e atualizar a lista de tarefas.

Assim vamos alterar o componente Tarefas.razor incluindo o evento no botão e o método PrepararExclusao() :

... 

<td><input type="button" class="btn btn-danger" @onclick="(() =>
PreparaExclusao(tarefa))
" data-toggle="modal" data-target="#confirmaExclusaoModal"
value="Deleta" /></td>

...

ConfirmaDialog OnClick="@Delete" />

<TarefaDetalhes TarefaObj=tarefaObject AlteracaoDados="@AlteracaoDados">
    <Cabecalho>@cabecalho</Cabecalho>
</TarefaDetalhes>

@code {
    List<Tarefa> tarefas;
    Tarefa tarefaObject = new Tarefa();
    string cabecalho = string.Empty;

    protected override async Task OnInitializedAsync()
    {
        tarefas = await service.Get();
    }
   ...   

    private void PreparaExclusao(Tarefa task)
    {
        tarefaObject = task;
    }

    ...

    private async Task Delete()
    {
        var task = await service.Delete(tarefaObject.Id);
        await js.InvokeAsync<object>("CloseModal", "confirmaExclusaoModal");
        tarefas = await service.Get();
        tarefaObject = new Tarefa();
    }

}

A seguir precisamos criar um novo  componente filho chamado ConfirmaDialog.razor na pasta Pages para solicitar a confirmação da exclusão do registro usando os recursos do diálogo modal do Bootstrap:

<div class="modal" tabindex="-1" role="dialog" id="confirmaExclusaoModal">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Confirmação</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">×</span>
                </button>
            </div>
            <div class="modal-body">
                <p>Deseja excluir este registro ?</p>
            </div>

            <div class="modal-footer">
                <button type="button" class="btn btn-primary" @onclick="OnClick">Sim</button>
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancela</button>
            </div>
        </div>
    </div>
</div>

@code {
    [Parameter]
    public int Id { get; set; }

    [Parameter]
    public EventCallback<MouseEventArgs> OnClick { get; set; }
}

Com isso temos tudo pronto para realizar o CRUD básico em tarefas usando os recursos do Blazor.

Executando o projeto teremos o resultado a seguir:

Pegue o projeto aqui:  BlazorTarefas.zip ...

"Meus filhinhos, escrevo-lhes estas coisas para que vocês não pequem. Se, porém, alguém pecar, temos um intercessor junto ao Pai, Jesus Cristo, o Justo."
1 João 2:1

Referências:


José Carlos Macoratti