Blazor - CRUD usando o Google Cloud Firestore - III


Hoje vamos continuar a criação da aplicação Blazor que realiza um CRUD básico usando o banco de dados Cloud Firestore.

Continuando a segunda parte do artigo vamos criar os componentes Blazor para acessar e persistir dados realizando o CRUD.

Criando o componente ListaAlunos.razor

Vamos criar um componente na pasta Pages do projeto Client e neste componente vamos definir todo o código para acessar e realizar as operações para incluir, alterar e excluir dados dos alunos.

Na pasta Pages crie o componente ListaAlunos.razor e inclua o código abaixo :

@page "/alunos"
@inject HttpClient _httpClient
<h1>Alunos</h1>
<div class="container">
    <div class="row">
        <div class="col-xs-3">
            <button class="btn btn-primary" data-toggle="modal" data-target="#AddEditAlunoModal" @onclick="@AddAluno">
                <i class="fa fa-user-plus"></i>
                Novo Aluno
            </button>
        </div>
        
        <div class="input-group col-md-4 offset-md-5">
            <input type="text" class="form-control" placeholder="Procurar Aluno" @bind="@searchString" />
            <div class="input-group-append">
                <button class="btn btn-info" @onclick="@SearchAluno">
                    <i class="fa fa-search"></i>
                </button>
            </div>
        </div>
    </div>
</div>
<br />
@if (alunos == null)
{
    <p><em>Carregando...</em></p>
}
else
{
    <table class='table'>
        <thead>
            <tr>
                <th>Nome</th>
                <th>Email</th>
                <th>Sexo</th>
                <th>Cidade</th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var aluno in alunos)
            {
                <tr>
                    <td>@aluno.Nome</td>
                    <td>@aluno.Email</td>
                    <td>@aluno.Sexo</td>
                    <td>@aluno.Cidade</td>
                    <td>
                        <button class="btn btn-outline-dark" data-toggle="modal" data-target="#AddEditAlunoModal"
                                @onclick="@(async () => await EditAluno(@aluno.AlunoId))">
                            <i class="fa fa-pencil-square-o"></i>
                            Editar
                        </button>
                        <button class="btn btn-outline-danger" data-toggle="modal" data-target="#DeleteAlunoModal"
                                @onclick="@(async () => await DeleteConfirma(@aluno.AlunoId))">
                            <i class="fa fa-trash-o"></i>
                            Deletar
                        </button>
                    </td>
                </tr>
            }
        </tbody>
    </table>
}
<div class="modal fade" id="AddEditAlunoModal">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title">@tituloModal</h3>
                <button type="button" class="close" data-dismiss="modal">
                    <span aria-hidden="true">X</span>
                </button>
            </div>
            <div class="modal-body">
                <form>
                    <div class="form-group">
                        <label class="control-label">Nome</label>
                        <input class="form-control" @bind="@aluno.Nome" />
                    </div>
                    <div class="form-group">
                        <label class="control-label">Sexo</label>
                        <select class="form-control" @bind="@aluno.Sexo">
                            <option value="">-- Sexo --</option>
                            <option value="Male">Masculino</option>
                            <option value="Female">Feminino</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label class="control-label">Email</label>
                        <input class="form-control" @bind="@aluno.Email" />
                    </div>
                    <div class="form-group">
                        <label class="control-label">Cidade</label>
                        <select class="form-control" @bind="@aluno.Cidade">
                            <option value="-- Cidade --">-- Cidade --</option>
                            @foreach (var cidade in cidades)
                            {
                                <option value="@cidade.Nome">@cidade.Nome</option>
                            }
                        </select>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button class="btn btn-block btn-success"
                        @onclick="@(async () => await SaveAluno())" data-dismiss="modal">
                    Salvar
                </button>
            </div>
        </div>
    </div>
</div>

<div class="modal fade" id="DeleteAlunoModal">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title">Confirmar Exclusão !!!</h3>
                <button type="button" class="close" data-dismiss="modal">
                    <span aria-hidden="true">X</span>
                </button>
            </div>
            <div class="modal-body">
                <table class="table">
                    <tr>
                        <td>Nome</td>
                        <td>@aluno.Nome</td>
                    </tr>
                    <tr>
                        <td>Sexo</td>
                        <td>@aluno.Sexo</td>
                    </tr>
                    <tr>
                        <td>Email</td>
                        <td>@aluno.Email</td>
                    </tr>
                    <tr>
                        <td>Cidade</td>
                        <td>@aluno.Cidade</td>
                    </tr>
                </table>
            </div>
            <div class="modal-footer">
                <button class="btn btn-danger" data-dismiss="modal"
                        @onclick="@(async () => await DeleteAluno(@aluno.AlunoId))">
                    Deletar
                </button>
                <button data-dismiss="modal" class="btn">Cancelar</button>
            </div>
        </div>
    </div>
</div>

@code{
    protected List<Aluno> alunos = new List<Aluno>();
    protected List<Cidade> cidades = new List<Cidade>();
    protected Aluno aluno = new Aluno();
    protected string tituloModal { get; set; }
    protected string searchString { get; set; }
    protected override async Task OnInitializedAsync()
    {
        await GetListaCidades();
        await GetListaAlunos();
    }
    protected async Task<List<Aluno>> GetListaAlunos()
    {
        alunos = await _httpClient.GetFromJsonAsync<List<Aluno>>("api/alunos");
        return alunos;
    }
    protected async Task GetListaCidades()
    {
        cidades = await _httpClient.GetFromJsonAsync<List<Cidade>>("api/alunos/GetCidades");
    }
    protected void AddAluno()
    {
        aluno = new Aluno();
        tituloModal = "Incluir Aluno";
    }
    protected async Task SearchAluno()
    {
        await GetListaAlunos();
        if (searchString != "")
        {
            alunos = alunos.Where(
            x => x.Nome.IndexOf(searchString,
            StringComparison.OrdinalIgnoreCase) != -1).ToList();
        }
    }

    protected async Task EditAluno(string alunoId)
    {
        aluno = await _httpClient.GetFromJsonAsync<Aluno>("/api/alunos/" + alunoId);
        tituloModal = "Editar Aluno";
    }

    protected async Task SaveAluno()
    {
        if (aluno.AlunoId != null)
        {
            await _httpClient.PutAsJsonAsync("api/alunos/", aluno);
        }
        else
        {
            await _httpClient.PostAsJsonAsync("/api/alunos/", aluno);
        }
        await GetListaAlunos();
    }

    protected async Task DeleteConfirma(string alunoId)
    {
        aluno = await _httpClient.GetFromJsonAsync<Aluno>("/api/alunos/" + alunoId);
    }

    protected async Task DeleteAluno(string alunoId)
    {
        Console.WriteLine(alunoId);
        await _httpClient.DeleteAsync("api/alunos/" + alunoId);
        await GetListaAlunos();
    }
}

Temos um monte de código em um único arquivo onde realizamos todas as operações CRUD. Para facilitar o entendimento vamos dividir o código em partes funcionais:

1- Na div 'container' definimos a inclusão de um novo aluno acionado pelo evento onclick que remete à div 'AddEditAlunoModal' e ao filtro dos alunos por nome:

<div class="container">
    <div class="row">
        <div class="col-xs-3">
            <button class="btn btn-primary" data-toggle="modal" data-target="#AddEditAlunoModal" @onclick="@AddAluno">
                <i class="fa fa-user-plus"></i>
                Novo Aluno
            </button>
        </div>        
        <div class="input-group col-md-4 offset-md-5">
            <input type="text" class="form-control" placeholder="Procurar Aluno" @bind="@searchString" />
            <div class="input-group-append">
                <button class="btn btn-info" @onclick="@SearchAluno">
                    <i class="fa fa-search"></i>
                </button>
            </div>
        </div>
    </div>
</div>

 

2- Na div AddEdtitAlunoModal tratamos a inclusão e também a alteração de dados de um aluno onde no evento onclick definimos o método SaveAluno():

<div class="modal fade" id="AddEditAlunoModal">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title">@tituloModal</h3>
                <button type="button" class="close" data-dismiss="modal">
                    <span aria-hidden="true">X</span>
                </button>
            </div>
            <div class="modal-body">
                <form>
                    <div class="form-group">
                        <label class="control-label">Nome</label>
                        <input class="form-control" @bind="@aluno.Nome" />
                    </div>
                    <div class="form-group">
                        <label class="control-label">Sexo</label>
                        <select class="form-control" @bind="@aluno.Sexo">
                            <option value="">-- Sexo --</option>
                            <option value="Male">Masculino</option>
                            <option value="Female">Feminino</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label class="control-label">Email</label>
                        <input class="form-control" @bind="@aluno.Email" />
                    </div>
                    <div class="form-group">
                        <label class="control-label">Cidade</label>
                        <select class="form-control" @bind="@aluno.Cidade">
                            <option value="-- Cidade --">-- Cidade --</option>
                            @foreach (var cidade in cidades)
                            {
                                <option value="@cidade.Nome">@cidade.Nome</option>
                            }
                        </select>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button class="btn btn-block btn-success"
                        @onclick="@(async () => await SaveAluno())" data-dismiss="modal">
                    Salvar
                </button>
            </div>
        </div>
    </div>
</div>

 

3- Na div DeleteAlunoModal apresentamos os dados do aluno a ser excluído e a implementação é feita no método DeleteAluno():

<div class="modal fade" id="DeleteAlunoModal">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title">Confirmar Exclusão !!!</h3>
                <button type="button" class="close" data-dismiss="modal">
                    <span aria-hidden="true">X</span>
                </button>
            </div>
            <div class="modal-body">
                <table class="table">
                    <tr>
                        <td>Nome</td>
                        <td>@aluno.Nome</td>
                    </tr>
                    <tr>
                        <td>Sexo</td>
                        <td>@aluno.Sexo</td>
                    </tr>
                    <tr>
                        <td>Email</td>
                        <td>@aluno.Email</td>
                    </tr>
                    <tr>
                        <td>Cidade</td>
                        <td>@aluno.Cidade</td>
                    </tr>
                </table>
            </div>
            <div class="modal-footer">
                <button class="btn btn-danger" data-dismiss="modal"
                        @onclick="@(async () => await DeleteAluno(@aluno.AlunoId))">
                    Deletar
                </button>
                <button data-dismiss="modal" class="btn">Cancelar</button>
            </div>
        </div>
    </div>
</div>

Para concluir vamos criar uma pasta image dentro da pasta wwwroot e incluir uma imagem de alunos.

A seguir na página Index.razor vamos incluir o código abaixo:

@page "/"
<img src="/image/alunos.jpg" class="img-fluid" />

 

Agora altere o código do arquivo NavMenu.razor conforme abaixo:

<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">Blazor_Firestorer</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="alunos">
                <span class="oi oi-plus" aria-hidden="true"></span> Alunos
            </NavLink>
        </li>
    </ul>
</div>
@code {
    private bool collapseNavMenu = true;
    private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
}

 

Executando o projeto iremos obter o seguinte resultado :

Pegue o projeto aqui :  Blazor_Firestore.zip (sem as referências)

"E, se não há ressurreição de mortos, também Cristo não ressuscitou.
E, se Cristo não ressuscitou, logo é vã a nossa pregação, e também é vã a vossa fé."
1 Coríntios 15:13,14

Referências:


José Carlos Macoratti