Hoje veremos imprimir no Blazor usando os recursos da interoperabilidade JavaScript. |
Se você esta chegando agora e não sabe o que é o Blazor leia o artigo ASP .NET Core - Iniciando com o Blazor - Macoratti; se você já conhece e quer saber mais pode fazer o curso de Blazor Essencial.
Com um pouco de interoperabilidade de JavaScript, podemos realizar muitas tarefas e uma delas é a impressão.
Sim, uma aplicação Blazor pode chamar funções JavaScript a partir dos métodos C#, e também podemos invocar métodos C# a partir do JavaScript.
Para mais detalhes leia o meu artigo: Blazor - Interoperabilidade com JavaScript - I
Hoje, vamos criar um projeto Blazor Server e acessar os dados da tabela Employees do banco de dados Northwind.mdf.
Se você não possui esse banco de dados baixe aqui: Baixar Northwind
Basta seguir as instruções e gerar o banco e as tabelas com os dados no seu ambiente.
Recursos usados:
Criando o projeto no VS Community 2019
Abra o VS 2019 Community (versão mínima 16.6) 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 : Blog_Print a localização e clique em Create;
Selecione a 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.
Com o projeto criado vamos limpar o projeto excluindo os arquivos abaixo e suas referências:
A seguir crie uma pasta images dentro da pasta wwwroot do projeto criado, e nesta pasta inclua os arquivos de imagens que iremos usar em nosso projeto.
Como vamos acessar dados do banco de dados Northwind.mdf do SQL Server vamos usar o Entity Framework e mapear para a tabela Employees para exibir algumas informações dos funcionários.
Inclua o pacote
Microsoft.EntityFrameworkCore.SqlServer no projeto
via menu Tools ou via comando :
install-package <nome>
Configurando o domínio e o contexto do EF Core
Vamos agora criar na pasta Data do projeto a classe Employee que representa o nosso domínio:
public class Employee
{
public int EmployeeId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string Address { get; set; }
public string City { get; set; }
} |
Criamos um DTO anêmico apenas para mapear algumas propriedades para as colunas da tabela Employees.
Ainda na pasta Data, vamos criar o arquivo de contexto AppDbContext onde vamos definir o mapeamento ORM:
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
public DbSet<Employee> Employees { get; set; }
}
|
Agora vamos registrar o contexto no método ConfigureServices da classe Startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
|
Precisamos criar agora a string de conexão no arquivo appsettings.json com o nome de DefaultConnection:
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=\\sqlexpress;Initial Catalog=Northwind;Integrated Security=True"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
|
Aqui você deve indicar a string de conexão do seu ambiente.
Pronto com isso já conseguimos acessar o banco de dados Northwind e a tabela Employees.
Criando o serviço para acessar os dados
Para poder acessar os dados da tabela Employees no SQL Server vamos criar a classe EmployeeService:
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Blazor_Print.Data
{
public class EmployeeService
{
private readonly AppDbContext _context;
public EmployeeService(AppDbContext context)
{
_context = context;
}
public async Task<List<Employee>> GetEmployees()
{
return await _context.Employees.ToListAsync();
}
}
}
|
Nosso objetivo é apenas obter os dados da tabela e por isso criamos apenas o método GetEmployees().
Só falta registrar o serviço no arquivo Startup:
public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddServerSideBlazor(); services.AddTransient<EmployeeService>(); services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
|
Definindo o menu e os componentes
Vamos definir as opções do menu da aplicação no arquivo NavMenu.razor da pasta Shared do projeto:
<div class="top-row pl-4 navbar navbar-dark">
<a class="navbar-brand" href="">Blazor_Print</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="employees" @onclick="()=> expandSubMenu1 = !expandSubMenu1">
<span class="oi oi-plus" aria-hidden="true"></span> Funcionários
</NavLink>
@if (expandSubMenu1)
{
<ul class="nav flex-column">
<li class="nav-item px-4">
<NavLink class="expand-menu" href="print">
<span class="oi oi-print" aria-hidden="true"></span> Imprimir
</NavLink>
</li>
</ul>
}
</li>
</ul>
</div>
@code {
private bool collapseNavMenu = true;
private bool expandSubMenu1;
private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
}
|
Neste código estamos criando a opção de menu Funcionários que mapeia para a rota employees e a seguir criamos um sub-menu Imprimir que mapeia para print.
A idéia e que ao acionar o link Funcionários o menu de impressão seja aberto.
Vamos abrir o arquivo Index.razor e incluir o código abaixo neste arquivo:
@page "/"
<h3>Imprimindo com Blazor via Javascript</h3>
<img src="/images/print.jpg" width="500" height="300" class="img-fluid" /> |
Este componente apenas exibe a página inicial do projeto com uma imagem.
Agora vamos criar o componente EmployeeList.razor na pasta Pages que vai exibir os dados dos funcionários:
@page "/employees"
@inject EmployeeService empService
<h3>Funcionários</h3>
@if (employees == null)
{
<img src="/images/basicloader.gif" />
}
else
{
<table class='table'>
<thead>
<tr>
<th>Nome</th>
<th>Sobrenome</th>
<th>Endereço</th>
<th>Cidade</th>
</tr>
</thead>
<tbody>
@foreach (var employee in employees)
{
<tr>
<td>@employee.FirstName</td>
<td>@employee.LastName</td>
<td>@employee.Address</td>
<td>@employee.City</td>
</tr>
}
</tbody>
</table>
}
@code {
List<Employee> employees;
protected override async Task OnInitializedAsync()
{
employees = await empService.GetEmployees();
}
}
|
Este componente será acionado quando o usuário clicar no menu Funcionários.
Ao clicar neste menu será aberto o submenu Imprimir que vai acionar o componente Print.razor:
@page "/print"
@inject IJSRuntime IJS
<h3>Imprimindo...</h3>
<img src="/images/printanima1.gif" width="300" height="300" class="img-fluid"/>
@code {
protected override async Task OnInitializedAsync()
{
await PrintEmployees();
}
public async Task PrintEmployees()
{
await IJS.InvokeAsync<object>("open", new object[] { "/printEmployees", "_blank" });
}
}
|
É neste código que estamos chamando o método PrintEmployees() que vai usar os recursos da interoperabilidade Javascript do Blazor para abrir o componente PrintEmployees.razor para impressão:
@layout BlankLayout
@page "/printEmployees"
@inject EmployeeService empService
<body onload="window.print()">
<br />
<br />
<h3>Funcionários</h3>
<br />
<br />
@if (employees == null)
{
<img src="/images/basicloader.gif" />
}
else
{
<table class='table'>
<thead>
<tr>
<th>Nome</th>
<th>Sobrenome</th>
<th>Endereço</th>
<th>Cidade</th>
</tr>
</thead>
<tbody>
@foreach (var employee in employees)
{
<tr>
<td>@employee.FirstName</td>
<td>@employee.LastName</td>
<td>@employee.Address</td>
<td>@employee.City</td>
</tr>
}
</tbody>
</table>
}
</body>
@code {
List<Employee> employees;
protected override async Task OnInitializedAsync()
{
employees = await empService.GetEmployees();
}
}
|
O código deste componente é quase igual ao do componente ListEmployees.razor mas note que o layout usado neste componente é definido em BlankLayout e que temos código Html usando javascript para impressão.
Na pasta Shared do projeto vamos criar o componente BlankLayout:
@inherits LayoutComponentBase
@Body
|
Pronto ! já podemos testar a impressão da lista de funcionários que implementamos usando Javascript.
Executando o projeto teremos o resultado a seguir:
Na próxima parte do artigo veremos como gerar um relatório customizado e imprimir via JavaScript.
Pegue o projeto aqui: Blazor_Print.zip (sem as referências)
"E em nada vos espanteis dos
que resistem, o que para eles, na verdade, é indício de
perdição, mas para vós de salvação, e isto de Deus.
Porque a vós vos foi concedido, em relação a Cristo, não
somente crer nele, como também padecer por ele"
Filipenses 1:28,29
ASP .NET Core - Iniciando com o Blazor
ASP .NET Core - CRUD usando Blazor e Entity ..
Blazor - O novo framework SPA da Microsoft
Visual Studio Code - Suporte ao desenvolvimento Blazor
Blazor - Passando dados para Componentes
ASP .NET Core - CRUD usando Blazor e Entity ...
Vale a pena usar o Blazor
ASP .NET Core Blazor - Gerenciando Usuários e Perfis