Blazor -  MatBlazor : Criando um Grid de Produtos


Hoje veremos como usar o componente MatTable da biblioteca MatBlazor e criar um Grid para exibir uma lista de produtos.

A biblioteca MatBlazor compreende uma variedade de componentes que implementam padrões de interação comuns, de acordo com a especificação do Material Design.

Você pode acessar a documentação e exemplos no site: https://www.matblazor.com/

Hoje vamos usar o componente MatTable e mostrar como exibir uma lista de produtos em um Grid.

Vamos acessar os dados a partir de um banco de dados SQL Server usando ADO .NET (para variar um pouco).

Recursos usados:

Criando o projeto Blazor Server no VS Community 2019

bra o VS 2019 Community (versão mínima 16.4) e selecione a opção Create a New Project;

A seguir selecione a opção Blazor app e clique em next;

Informe o nome do projeto :  Blazor_MathGrid, a localização e clique em Create;

A seguir teremos uma janela com duas opções :

  1. Blazor Server App
  2. Blazor WebAssembly App

Selecione a primeira opção - Blazor Server App. Não vamos usar autenticação e vamos habilitar o https.

Clique no botão Create para criar o projeto.

Antes de prosseguir vamos limpar o projeto excluindo os arquivos abaixo e suas referências:

Vamos também ajustar o arquivo NavMenu.razor deixando apenas a opção Home e a opção Produtos para acessar o componente Produtos.razor que iremos criar para exibir o grid.

<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="produtos">
                <span class="oi oi-person" aria-hidden="true"></span> Produtos
            </NavLink>
        </li>
    </ul>
</div>

Agora com o projeto criado e os ajustes feitos vamos incluir a referência ao pacote nuget que vamos usar.

Configurando o projeto : Referenciando o pacote MatBlazor

Clique no menu Tools > NuGet Package Manager > Manage NuGet Package For Solution.

E na guia Browse procure pelo pacote MatBlazor e instale o pacote no seu projeto:

NotaVocê também pode instalar usando a janela do Gerenciador de pacotes com o comando:
Install-Package MatBlazor -Version 2.2.0

Com o projeto criado vamos criar uma pasta images dentro da pasta wwwroot e incluir algumas imagens que iremos usar no projeto:

Abra o arquivo _Imports.razor  do projeto e inclua as referência aos namespaces @using MatBlazor e @using Blazor_MathGrid.Data;

Essas referências serão usadas em nosso projeto pelos componentes que iremos criar.

@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using Blazor_MathGrid
@using Blazor_MathGrid.Shared
@using MatBlazor
@using Blazor_MathGrid.Data

Agora abra o arquivo _Host.cshtml da pasta Pages inclua uma referência ao arquivo Javascript matBlazor.js e ao arquivo de estilo matBlazor.css na seção header do arquivo:

@page "/"
@namespace Blazor_MathGrid.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
    Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Blazor_MathGrid</title>
    <base href="~/" />
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />

    <script src="_content/MatBlazor/dist/matBlazor.js"></script>
    <link href="_content/MatBlazor/dist/matBlazor.css" rel="stylesheet"/>

</head>
<body>
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    <div id="blazor-error-ui">
        <environment include="Staging,Production">
            An error has occurred. This application may no longer respond until reloaded.
        </environment>
        <environment include="Development">
            An unhandled exception has occurred. See browser dev tools for details.
        </environment>
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.server.js"></script>
</body>
</html>

Criando um serviço para acessar os dados

Vamos aproveitar a pasta Data já criada no projeto e nesta pasta criar a classe Produto que representa o nosso um produto e que é o nosso domínio:

Crie o arquivo Produto.cs e inclua o código abaixo:

    public class Produto
    {
        public int ProdutoId { get; set; }
        public string Nome { get; set; }
        public string Descricao { get; set; }
        public decimal Preco { get; set; }
        public bool Ativo { get; set; }
        public string ImagemUrl { get; set; }
    }

Agora vamos criar a interface IProdutoService onde vamos definir a assinatura do método para retornar os dados dos produtos:

    public interface IProdutoService
    {
        Task<List<Produto>> GetProdutos();
    }

A seguir vamos implementar essa interface na classe ProdutoService onde vamos criar o método GetProdutos que acessa a tabela Produtos e retorna uma lista de produtos:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Threading.Tasks;
namespace Blazor_MathGrid.Data
{
    public class ProdutoService : IProdutoService
    {
        private readonly SqlConnectionConfiguration _configuration;
        public ProdutoService(SqlConnectionConfiguration configuration)
        {
            _configuration = configuration;
        }        
        public async Task<List<Produto>> GetProdutos()
        {
            List<Produto> produtos = new List<Produto>();
            try
            {
                using (SqlConnection con = new SqlConnection(_configuration.ConnectionString))
                {
                    const string query = "Select * from Produtos";
                    SqlCommand cmd = new SqlCommand(query, con)
                    {
                        CommandType = CommandType.Text
                    };
                    con.Open();
                    SqlDataReader rd = await cmd.ExecuteReaderAsync();
                    while (rd.Read())
                    {
                        Produto produto = new Produto
                        {
                            ProdutoId = Convert.ToInt32(rd["ProdutoId"]),
                            Nome = rd["Nome"].ToString(),
                            Descricao = rd["Descricao"].ToString(),
                            Preco = Convert.ToDecimal(rd["Preco"]),
                            Ativo = Convert.ToBoolean(rd["Ativo"]),
                            ImagemUrl = rd["ImagemUrl"].ToString(),
                        };
                        produtos.Add(produto);
                    }
                    cmd.Dispose();
                }
                return produtos;
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}

Neste código estamos usando os recursos da ADO .NET para acessar os dados do SQL Server.

Injetamos no construtor da classe uma instância da classe SqlConnectionConfiguration para obter a string de conexão com o nosso banco de dados SQL Server.

A seguir definimos uma conexão usando SqlConnection com a string de conexão obtida e um comando com SqlCommand onde passamos a instrução SQL para obter os produtos.

A seguir usando um SqlDataReader acessamos os dados e montamos  uma lista de objetos produtos que é retornada.

Precisamos então criar a classe  SqlConnectionConfiguration  que vai obter a string de conexão a partir do arquivo appsettings.json:

    public class SqlConnectionConfiguration
    {
        public string ConnectionString { get; }
        public SqlConnectionConfiguration(string stringConexao)
            => this.ConnectionString = stringConexao;
    }

Aqui criamos a propriedade ConnectionString que retorna a string de conexão.

Agora temos que registrar o serviço criado no método ConfigureServices da classe Startup, temos que obter a string de conexão e também registrar a classe ConnectionConfiguration como um serviço do tipo Singleton para obtermos uma única instância da nossa conexão.

        public void ConfigureServices(IServiceCollection services)
        {
            var sqlConnectionConfiguration = new SqlConnectionConfiguration(
                Configuration.GetConnectionString("ProdutosADONETConnection"));
            services.AddSingleton(sqlConnectionConfiguration);
            services.AddRazorPages();
            services.AddServerSideBlazor();

            services.AddScoped<IProdutoService, ProdutoService>();
            services.AddScoped<HttpClient>();
        }

Além disso precisamos do serviço HttpClient para usar os recursos da MatBlazor.

NotaSugiro que você leia este artigo: Hutch Codes — Dependency Injection Lifetimes in Blazor

Para concluir inclua no arquivo appsettings.json a string de conexão do SQL Server usado para armazenar os dados dos produtos:

{
  "ConnectionStrings": {
    "ProdutosADONETConnection": "
Sua string de conexão;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Criando o componente Produtos para exibir os produtos

Vamos criar o componente Produtos.razor na pasta Pages do projeto para poder exibir a lista de produtos usando o componente MatTable.

Crie o arquivo Produtos.razor na pasta Pages com o código abaixo:

@page "/produtos"
@inject IProdutoService  produtoService
@if (produtos == null)
{
    <div>
        <img src="/images/basicloader.gif" />
    </div>
}
else
{
    <MatTable Items="@produtos" Class="mat-elevation-z5" AllowSelection="true">
        <MatTableHeader>
            <th>Código</th>
            <th>Nome</th>
            <th>Descricao</th>
            <th>Preco</th>
            <th>Imagem</th>
        </MatTableHeader>
        <MatTableRow>
            <td>@context.ProdutoId</td>
            <td>@context.Nome</td>
            <td>@context.Descricao</td>
            <td>@string.Format("{0:C2}",context.Preco)</td>
            <td><img src="@context.ImagemUrl" height="80" width="80"/></td>
        </MatTableRow>
    </MatTable>
}
@code {
    List<Produto> produtos;
    protected override async Task OnInitializedAsync()
    {
        produtos = await produtoService.GetProdutos();
    }
}

Aqui usamos o componente MatTable definindo os produtos a serem exibidos em Items e criando o layout do Grid usando MatTableHeader e MatTableRow.

Os dados são obtidos no método OnInitializedAsync onde usamos a instância do serviço que foi injetado no arquivo.

Agora é só alegria...

Executando o projeto teremos o resultado abaixo:

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

"Vós me chamais Mestre e Senhor, e dizeis bem, porque eu o sou.
Ora, se eu, Senhor e Mestre, vos lavei os pés, vós deveis também lavar os pés uns aos outros.
Porque eu vos dei o exemplo, para que, como eu vos fiz, façais vós também."
João 13:13-15

Referências:


José Carlos Macoratti