Aplicações Web rápidas com ASP.NET Core e Shield UI

Entenda como a componentização do Shield UI pode flexibilizar o desenvolvimento de suas aplicações web em ASP.NET.

Fique por dentro
Este artigo é útil por apresentar os conceitos e práticas mais importantes acerca do framework de componentes do Shield UI. Nascido para facilitar o desenvolvimento de softwares web, o Shield UI fornece uma série de componentes prontos e fáceis de customizar que podem se integrar com os mais diversos tipos de aplicações web, sejam elas em ASP.NET (Core ou MVC), sejam em tecnologias como Java, HTML, etc. Aqui, você terá insumos e instruções sobre como integrá-lo aos seus projetos ASP.NET Core, bem como popular widgets via serviços RESTful.

Desenvolver aplicações web na plataforma .NET é uma tarefa que se torna cada vez mais simples há cada lançamento de atualizações da Microsoft. O Visual Studio, aliado aos plugins e componentes mantidos pela companhia, facilita a criação e automatização de códigos, CRUDS, integrações, dentre outros, ao passo em que viabiliza que o desenvolvedor foque em partes mais importantes do software como um todo. Em contrapartida, cada vez mais complexidades como a comunicação direta com determinados frameworks, toda a parte front-end, o banco de dados, são adicionados ao sistema final, o que exige certa proficiência do time para unificar tudo de forma concisa e funcional.

O Bootstrap é um dos frameworks front-end mais usados na atualidade e a forma como ele simplifica a criação e customização de componentes web tornou-se não só seu maior diferencial, como a principal razão por ser adotado pela maioria das plataformas, bem como respectivos desenvolvedores. Todos os tipos de aplicações se encaixam bem no visual/estrutura do Bootstrap, desde aplicações corporativas, educacionais, financeiras, de notícias, isso sem falar do lado responsivo bem encapsulado pelo framework para todos os tipos de dispositivos.

E quando se trata de mesclar o que há de melhor nos dois mundos, chegamos num ponto onde a maioria dos desenvolvedores entrava: como integrar tecnologias tão distintas de forma limpa, sem criar enlaces que tornem a manutenção do sistema difícil no futuro? A resposta mais simples está em conhecer bem ambas as tecnologias. A plataforma .NET, especificamente, fornece inúmeros recursos para lidar com elementos web de forma simplificada, incluindo diversas bibliotecas JavaScript que já têm inclusão automática feita pelo gerenciador de dependências do Visual Studio, como o jQuery, por exemplo.

Neste artigo, trataremos de expor as principais facetas desse tipo de processo, através da criação de uma aplicação totalmente responsiva de gerenciamento escolar, alunos, notas, disciplinas, etc. de modo a expor o passo a passo requerido na hora de incutir estilos, elementos e widgets do Bootstrap em conjunto com o desenvolvimento de scripts web, bem como toda a parte JavaScript do cliente. Neste, especialmente, faremos uso do framework Shield UI, já conhecido dos desenvolvedores .NET por sua fácil integração com a plataforma, com o jQuery, dentre outros.

Configurando o ambiente

Antes de qualquer coisa, certifique-se de que tem o ambiente devidamente configurado com uma versão recente do Visual Studio, além das opções “ASP.NET and web development” e “.NET Core cross-platform development” quando estiver instalando a IDE. Isso é tudo para que possamos criar um projeto do tipo ASP.NET Core MVC. Para isso, seleciona a opção “Arquivo > Novo > Projeto...” e, em seguida, nos modelos instalados, selecione a opção tal como mostrado na Figura 1.

Figura 1. Criando novo projeto Web ASP.NET Core

Em seguida, selecione a opção que representa o tipo de aplicação para web, que encapsula tanto os controladores do MVC quanto o modelo RESTful, tal como demonstrado na Figura 2.

Figura 2. Selecionando o tipo de template do projeto

Para iniciar as configurações do Shield UI no nosso projeto, basta clicar com o botão direito no mesmo e selecionar a opção “Gerenciar pacotes do NuGet...”. Na aba “Procurar”, digite o texto “ShieldUI.AspNetCore.Mvc”, clique em pesquisar e na opção que aparecer clique em “Instalar”. Caso algum erro seja apresentado durante esse procedimento, revise as versões máximas que o Shield UI suporta (ele informará a mesma no Console de erros, uma vez que a última versão que o autor estiver usando pode não mais ser a mesma da data de escrita deste artigo).

Uma vez com o app criado e a dependência do Shield UI devidamente adicionada ao projeto, precisamos importar suas classes de inicialização nos arquivos de configuração do projeto .NET. A primeira delas no arquivo de views /_ViewImports.cshtml, o qual define o resumo de recursos externos que as páginas web da webapplication terão acesso liberado. A mesma conta apenas com os tag helpers padrão da Microsoft, bem como o do próprio projeto. Portanto, adicione a seguinte linha de código ao fim do arquivo:

@using ShieldUI.AspNetCore.Mvc

Asegunda configuração, já no código C#, consiste em adicionar a inicialização e respectivo uso da API do Shield UI no arquivo de startup do projeto, o Startup.cs. Há dois métodos que devemos alterar: o primeiro é método Configure(), que recebe o objeto de IApplicationBuilder para configuração de recursos específicos que a aplicação fará uso. Vejamos na Listagem 1 como o mesmo deve ficar.

Listagem 1. Método Configure() pós configuração do Shield UI.

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseBrowserLink(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); app.UseShieldUI(); }

Perceba logo no início do método o recurso de diferenciação de ambientes de desenvolvimento, fornecido através do objeto IHostEnvironment, o qual facilita a forma como configuramos e direcionamos determinadas implementações para ambientes específicos: desenvolvimento, teste, produção, etc. Se desejar, o leitor pode trabalhar também definindo testes específicos de gráficos ou telas que funcionarão apenas a nível local ou no QA, por exemplo, flexibilizando muito o processo inteiro. As demais configurações são bem simples e usuais, a considerar o fato de já estarmos definindo também a rota padrão da Home (ação de Index) para o roteamento de requisições e endpoints (o default define qual o endpoint referente à página inicial). Por fim, temos a configuração que diz ao projeto para usar os recursos disponibilizados pelo Shield UI. Isso só é possível graças à disponibilização do objeto em um segundo método: o método ConfigureServices() (vide Listagem 2).

Listagem 2. Configuração do método ConfigureServices().

// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddMvc(); // add Shield UI services.AddShieldUI(); }

Este, por sua vez, é bem conhecido dos desenvolvedores .NET MVC, uma vez que adiciona os recursos do framework da plataforma para o tipo de projeto selecionado: MVC. Além disso, também estamos adicionando os serviços do Shield UI, para que se torne acessíveis do ponto de vista gerencial pelo build da ferramenta. Para garantir que as configurações surtam o devido efeito, adicione no bloco de imports do início do arquivo o seguinte import:

using ShieldUI.AspNetCore.Mvc;

Nosso próximo passo será a adição dos recursos web do framework Shield UI, arquivos JavaScript e CSS, que trazem os bundles necessários para construir a interface web final, via componentização. Para isso, efetue o download do pacote mais recente JavaScript do Shield UI (vide seção Links), descompacte-o e renomeie o nome do diretório raiz de modo a remover os números de versão, bem como quaisquer caracteres especiais. Adicione o mesmo à pasta wwwroot/lib do projeto, tal como vemos na Figura 3.

Figura 3. Estrutura de diretórios do Shield UI web

O Shield UI tem dependência explicita nos pacotes do jQuery, o qual já vem adicionado por padrão no projeto. Para ter nosso primeiro exemplo funcional, precisamos importar os arquivos de CSS e JavaScript na tag <head> da nossa página. Para garantir que os mesmos serão importados em todas por padrão, faremos isso diretamente nos arquivos de layout. Portanto, abra o arquivo /Views/Shared/_Layout.cshtml e adicione as linhas de código apresentadas na Listagem 3 antes do fechamento da tag em questão.

Listagem 3. Importação dos scripts e estilos do Shield UI + jQuery.

<script src="~/lib/jquery/dist/jquery.js"></script> <script src="~/lib/shieldui/js/shieldui-all.min.js"></script> <link rel="stylesheet" href="~/lib/shieldui/css/light/all.min.css" /> </head>

Isso será o bastante para inicializar os recursos estáticos do framework. Como primeiro exemplo, vamos usar o arquivo /Views/Home/Index.cshtml para criar um gráfico de resumo das matrículas realizadas nos últimos anos. Para isso, altere todo o conteúdo da referida página para o demonstrado na Listagem 4.

Listagem 4. Conteúdo de exemplo do gráfico de resumo de matrículas.

@{ ViewData["Title"] = "Resumo de Matrículas"; } <h1>Resumo: 2016-2017</h1> @(Html.ShieldChart() .Name("grafico_matriculas") .Tooltip(tooltip => tooltip.AxisMarkers(axisMarkers => axisMarkers .Enabled(true) .Mode(ShieldUI.AspNetCore.Mvc.Chart.TooltipAxisMarkerMode.XY) .Width(1) .ZIndex(3))) .Theme("dark") .PrimaryHeader(header => header.Text("Cenário do Semestre") .Style(style => style.FontSize("25"))) .SecondaryHeader(header => header .Text("<i>Demonstrativo Inicial (Incluindo Anseios de Matrícula)</i>") .Style(style => style.Color("yellow"))) .Export(true) .AxisX(axis => axis.CategoricalValues( "2016.1", "2016.2", "2017.1", "2017.2", "2018.1" )) .DataSeries(series => series.Area() .Name("Qtd Alunos Matriculados") .Data(new object[] { 345, 234, 398, 323, 0 }) ) )

Todo o código autogerado pelo Visual Studio, com Bootstrap e carousel, foi substituído por nada mais que um script C# que faz uso direto das classes do ShielUI. Vejamos alguns pontos importantes:

O resultado do gráfico pode ser visualizado na Figura 4. Para executar o projeto, basta salvar todos os arquivos alterados e executar via atalho F5.

Figura 4. Gráfico final com valores em exibição em azul

CRUD

As operações possíveis sobre os diferentes tipos de gráficos no Shield UI são inúmeras, mas seguem praticamente a mesma linha de implementação. Uma gama de métodos disponibilizados pode ou não ser usados em conjunto para alcançar diferentes resultados. Em função disso, vejamos agora como lidar com métodos básicos de CRUD usando o widget de grid do framework, o qual nos possibilita criar facilmente tabelas editáveis, ordenáveis, selecionáveis, etc.

Para tanto, faremos uso de um modelo de dados simples, com uma entidade de Aluno que conterá algumas propriedades básicas a serem cadastradas, visualizadas, editadas e/ou removidas. Em vista de facilitar o trabalho com a base de dados, faremos uso do provider InMemory do Entity Framework Core para criar e lidar com operações de banco em memória, facilitando bastante o trabalho de testes e do próprio desenvolvimento. Portanto, acesse novamente o gerenciador de pacotes do NuGet e busque pelo seguinte pacote “Microsoft.EntityFrameworkCore.InMemory”, instale-o no nosso projeto.

Após isso, precisamos fazer com que o namespace do Entity Framework esteja visível na classe de Startup.cs. Para isso, adicione as seguintes linhas de código ao final da importação de classes:

using Microsoft.EntityFrameworkCore; using Educa_App.Models;

Isso será o suficiente para que tanto o framework quanto as classes de modelo que criaremos sejam enxergáveis pelo contexto do ASP.NET. No método ConfigureServices(), adicione também o seguinte trecho de código ao final:

services.AddDbContext<AlunoContext>(opt => opt.UseInMemoryDatabase());

Não se preocupe se der algum erro com a classe AlunoContext ou com o namespace. Isso acontece porque precisamos criar também o diretório onde tais arquivos existirão. Logo, crie uma nova pasta no projeto chamadO “Models” clicando com o botão direito no projeto e selecionando a opção “Adicionar > Nova pasta”. Em seguida, crie duas novas classes: Aluno.cs (vide Listagem 5) e AlunoContext.cs (vide Listagem 6). Veja que a primeira representa apenas um POJO de objeto simples, com atributos e get’s/set’s para os mesmos compondo um domínio de alunos. A segunda, por sua vez, herda de DbContext para incutir funcionalidade referente às operações de banco de dados, fornecendo métodos default de CRUD através do objeto de modelo passado, no caso Aluno.

Listagem 5. Conteúdo da classe Aluno.cs.

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Educa_App.Models { public class Aluno { public long Id { get; set; } public string Nome { get; set; } public int Idade { get; set; } public DateTime DtNasc { get; set; } public bool IsMatriculado { get; set; } public decimal Valor { get; set; } } }

Listagem 6. Conteúdo da classe AlunoContext.cs.

namespace Educa_App.Models { public class AlunoContext : DbContext { public AlunoContext(DbContextOptions<AlunoContext> options) : base(options) { } public DbSet<Aluno> Alunos { get; set; } } }

Agora precisamos lidar com a criação dos métodos de serviço, especificamente Restful, para tratar as requisições de CRUD de cada aluno. Portanto, clique com o botão direito na pasta de Controllers do projeto e selecione a opção “Adicionar > Novo Item” e, em seguida, a opção representada na Figura 5.

Figura 5. Criando novo controller no projeto

Depois de criada, você notará que a classe já vem com uma estrutura mínima pré-construída para métodos de CRUD, a despeito dos benefícios de usar essa versão mais recente do Visual Studio. Isso já ajuda bastante a adaptar o modelo ao nosso CRUD em específico, além de atrelar as operações ao respectivo banco de dados. A Listagem 7 traz todo o conteúdo da classe recém gerada.

Listagem 7. Endpoints do serviço de Alunos.

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Educa_App.Models; namespace Educa_App.Controllers { [Route("api/[controller]")] public class AlunoController : Controller { private readonly AlunoContext _context; public AlunoController(AlunoContext context) { _context = context; if (_context.Alunos.Count() == 0) { _context.Alunos.Add(new Aluno { Nome = "João Caruzo", Idade = 43, DtNasc = DateTime.Today, IsMatriculado = true, Valor = 355.34m }); _context.Alunos.Add(new Aluno { Nome = "Joana D'Arc", Idade = 22, DtNasc = DateTime.Today, IsMatriculado = false, Valor = 456.00m }); _context.Alunos.Add(new Aluno { Nome = "Alisson Matos", Idade = 19, DtNasc = DateTime.Today, IsMatriculado = false, Valor = 456.00m }); _context.Alunos.Add(new Aluno { Nome = "Maria Silva", Idade = 29, DtNasc = DateTime.Today, IsMatriculado = false, Valor = 456.00m }); _context.Alunos.Add(new Aluno { Nome = "Celton Souza", Idade = 23, DtNasc = DateTime.Today, IsMatriculado = true, Valor = 456.00m }); _context.SaveChanges(); } } // GET: api/aluno [HttpGet] public IEnumerable<Aluno> Get() { return _context.Alunos.ToList(); } // GET api/aluno/5 [HttpGet("", Name = "GetAluno")] public IActionResult Get(int id) { var aluno = _context.Alunos.FirstOrDefault(t => t.Id == id); if (aluno == null) { return NotFound(); } return new ObjectResult(aluno); } // POST api/aluno [HttpPost] public IActionResult Post([FromBody] Aluno aluno) { if (aluno == null) { return BadRequest(); } _context.Alunos.Add(aluno); _context.SaveChanges(); return CreatedAtRoute("GetAluno", new { id = aluno.Id }, aluno); } // PUT api/aluno/5 [HttpPut("")] public IActionResult Put(long id, [FromBody] Aluno aluno) { if (aluno == null || aluno.Id != id) { return BadRequest(); } var alunoUpdate = _context.Alunos.FirstOrDefault(t => t.Id == id); if (alunoUpdate == null) { return NotFound(); } alunoUpdate.Nome = aluno.Nome; alunoUpdate.Idade = aluno.Idade; alunoUpdate.DtNasc = aluno.DtNasc; alunoUpdate.Valor = aluno.Valor; alunoUpdate.IsMatriculado = aluno.IsMatriculado; _context.Alunos.Update(alunoUpdate); _context.SaveChanges(); return new NoContentResult(); } // DELETE api/aluno/5 [HttpDelete("")] public IActionResult Delete(int id) { var todo = _context.Alunos.First(t => t.Id == id); if (todo == null) { return NotFound(); } _context.Alunos.Remove(todo); _context.SaveChanges(); return new NoContentResult(); } } }

Veja que, logo no início, já temos a primeira rota para a raiz do controller definida através do endpoint /api/, o qual obviamente pode ser alterado a bel-prazer. O construtor da classe, por sua vez, se encarregará de iniciar o contexto que criamos anteriormente para assegurar um objeto centralizado para as operações de banco. Veja que, via injeção de dependências, já recebemos o referido objeto por parâmetro, apenas associando-o a uma variável global e, em seguida, criando uma lista de cinco alunos na base em memória, apenas para que nosso exemplo já tenha valores em banco para testes. O leitor pode ficar à vontade para customizar tal inicialização como quiser.

Em relação aos demais métodos de serviço, perceba que cada um vem com um comentário logo acima da sua assinatura, para facilitar o entendimento sobre como devemos chamá-lo via requisição, bem como que método HTTP corresponde a cada um. Vejamos:

NOTA: O leitor pode fazer uso de quaisquer ferramentas de teste de serviços, como o Postman, por exemplo, para testar cada um dos métodos antes de prosseguir para o consumo dos mesmos nas telas. Isso é útil, pois tais ferramentas facilitam o teste e correções de bugs como um todo.

Em se tratando do código Shield UI e as exibições de tela, reaproveitaremos a página de Contato pré-criada pela inicialização do projeto. Para isso, precisaremos alterar em três lugares distintos:

Abra agora o arquivo Alunos.cshtml e remova todo o seu conteúdo. Como se trata de uma implementação extensa, a dividiremos em duas partes (Listagens 8 e 9) para facilitar o entendimento.

Listagem 8. Código da grid Shield UI – parte 1.

@{ ViewData["Title"] = "Lista de Alunos"; } <h1>Lista de Alunos</h1> @(Html.ShieldGrid() .Name("tabela_alunos") .DataSource(ds => ds .Remote(rb => rb .ReadConfiguration(r => r .Add("type", "GET") .Add("url", "/api/aluno") .Add("dataType", "json")) .ModifyObject(m => m .Modify(ShieldUI.AspNetCore.Mvc.DataSource.ModifyOptions.Create, @<text>function(alunos, success, error) { var novoAluno = alunos[0]; $.ajax({ type: "POST", url: "/api/aluno", dataType: "json", data: JSON.stringify(novoAluno.data), contentType: "application/json", complete: function(xhr) { if (xhr.readyState == 4) { if (xhr.status == 201) { var location = xhr.getResponseHeader("Location"); novoAluno.data.Id = +location.replace(/^.*?\/([\d]+)$/, "$1"); success(); return; } } error(xhr); } }); }</text>) .Modify(ShieldUI.AspNetCore.Mvc.DataSource.ModifyOptions.Update, @<text>function(alunos, success, error) { $.ajax({ type: "PUT", url: "/api/aluno/" + alunos[0].data.Id, dataType: "json", contentType: "application/json", data: JSON.stringify(alunos[0].data) }).then(success, error); }</text>) .Modify(ShieldUI.AspNetCore.Mvc.DataSource.ModifyOptions.Remove, @<text> function(alunos, success, error) { $.ajax({ type: "DELETE", url: "/api/aluno/" + alunos[0].data.Id }).then(success, error); }</text>))) .Events(eb => eb .Error(@<text>function(event) { if (event.errorType == "transport") { alert("Erro transport: " + event.error.statusText); // recarrega o datasource se a operação que falhou for salva if (event.operation == "save") { this.read(); } } else { // outro erro de datasource error - validação, etc switch (event.path.trim()) { case "Nome": event.editor.element.css("border-color", "red"); alert("O campo Nome não pode estar vazio"); break; case "Idade": event.editor.element.css("border-color", "red"); alert("O campo Idade não pode estar vazio"); break; case "DtNasc": event.editor._wrapper.css("border-color", "red"); event.editor._visibleInput.addClass("invalid-back"); alert("O campo Data de Nasc. não pode estar vazio"); break; default: alert(event.errorType + " erro: " + event.error); break; } } }</text>)) .Schema(sb => sb .Fields("Id", fb => fb.Path("id").Type(ShieldUI.AspNetCore.Mvc .DataSource.FieldType.Number).Nullable(false)) .Fields("Nome", fb => fb.Path("nome").Type(ShieldUI.AspNetCore.Mvc .DataSource.FieldType.String).Nullable(false).Validator (@<text>nomeValidator</text>)) .Fields("Idade", fb => fb.Path("idade") .Type(ShieldUI.AspNetCore.Mvc.DataSource.FieldType.Number) .Nullable(false).Validator(@<text>idadeValidator</text>)) .Fields("DtNasc", fb => fb.Path("dtNasc").Type(ShieldUI.AspNetCore .Mvc.DataSource.FieldType.Date).Nullable(false)) .Fields("Valor", fb => fb.Path("valor").Type(ShieldUI.AspNetCore.Mvc .DataSource.FieldType.Number).Nullable(false)) .Fields("IsMatriculado", fb => fb.Path("isMatriculado") .Type(ShieldUI.AspNetCore.Mvc.DataSource.FieldType.Boolean))))

Aqui podemos ver definições bem semelhantes às que fizemos no primeiro gráfico Shield UI. A inicialização, exceto pelo método ShieldGrid() dessa vez, seguem o mesmo padrão. O método DataSource() é obrigatório pois é nele onde efetuamos as principais relativas à fonte de dados, no caso os serviços Restful. Vejamos a sequência de chamadas por método:

Listagem 9. Código da grid Shield UI – parte 2.

.Sorting(true) .RowHover(true) .Columns(cb => cb .Field("Id").Title("Id").Width(80) .Attributes(ab => ab.Style("text-align: center;")) .HeaderAttributes(ha => ha.Style("text-align: center;"))) .Columns(cb => cb.Field("Nome").Title("Nome").Width(200) .Format(@<text> function(value) { return "<strong>" + value + "</strong>"; } </text>)) .Columns(cb => cb .Field("Idade").Title("Idade").Width(80) .Attributes(ab => ab.Style("text-align: center;")) .HeaderAttributes(ha => ha.Style("text-align: center;"))) .Columns(cb => cb .Field("DtNasc").Title("Dat Nasc.").Format("{0:dd/MM/yyyy}").Width(120)) .Columns(cb => cb .Field("Valor").Title("Valor").Width(120) .Format("{0:c}") .Attributes(ab => ab.Style("text-align: left;")) .HeaderAttributes(ha => ha.Style("text-align: left;"))) .Columns(cb => cb .Field("IsMatriculado").Title("Matriculado?").Width(100) .Attributes(ab => ab.Style("text-align: center;")) .HeaderAttributes(ha => ha.Style("text-align: center;"))) .Columns(cb => cb.Width(200).Title("Ações") .Buttons(b => b.CommandName("edit").Caption("Editar")) .Buttons(b => b.CommandName("delete").Caption("Deletar")) .HeaderAttributes(ha => ha.Style("text-align: center;"))) .ToolBar(tb => tb.Buttons(b => b.CommandName("insert") .Caption("Novo Aluno")) .Position(ShieldUI.AspNetCore.Mvc.Grid.PositionOptions.Top)) .ToolBar(tb => tb.Buttons(b => b.Caption("Recarregar lista") .Click(@<text> function(e) { var grid = this; $.ajax({ type: "GET", url: "/api/aluno" }).done(function() { grid.dataSource.read(); }); }<text>)) .Position(ShieldUI.AspNetCore.Mvc.Grid.PositionOptions.Bottom)) .PagingConfiguration(pb => pb.PageSize(4)) .Editing(eb => eb.Enabled(true) .Type(ShieldUI.AspNetCore.Mvc.Grid.EditingTypeOptions.Row))) <script type="text/javascript"> function idadeValidator(value) { if (value <= 0) { return undefined; } else { return value; } } function nomeValidator(value) { if (value == "") { return undefined; } else { return value; } } </script>

Vejamos nessa continuação de código da Listagem 7 algumas de suas principais definições:

CRUD finalizado, agora é só reexecutar a aplicação e testar suas funcionalidades. As Figuras 6 a 8 demonstram alguns fluxos de funcionamento da tela.

Figura 6. Listagem padrão com limite de quatro alunos por página
Figura 7. Editando um item da tabela
Figura 8. Mensagens de validação padrão

Uma vez entendidos os conceitos mais centrais do framework e a forma como cada método se encadeia em chamadas, usar o Shield UI se torna uma tarefa fácil e intuitiva. Até mesmo quando precisamos migrar para outras versões do ASP.NET ou demais tecnologias que o Shield UI suporta, o trabalho não se torna maçante. Por exemplo, vejamos como adaptar a nossa página About tal como vemos na Listagem 10. Nele, estamos efetuando uma mescla entre os componentes de tabs, um dos widgets HTML também fornecidos pelo Shield UI para flexibilizar a componentização de páginas web, e outros tipos de gráficos do mesmo.

Listagem 10. Código com gráficos e tabs.

@{ ViewData["Title"] = "About"; } <h1>About</h1> <div id="tabsContainer"> @(Html.ShieldTabs() .Name("tabsDiv") .Html(@<text> <ul> <li>Média Etária</li> <li>Mercury</li> </ul> <div> @(Html.ShieldChart() .Name("chart1") .Theme("dark") .Export(false) .PrimaryHeader(header => header.Text("Distribuição Etária dos Alunos")) .ChartLegend(legend => legend.Enabled(true)) .SeriesSettings(setting => setting.Pie(pie => pie .EnablePointSelection(true))) .DataSeries(dataSeries => dataSeries.Pie() .CollectionAlias("Faixa") .Data(new object[] { new object[] {"Até 20 anos", 40}, new object[] {"Dos 20 aos 30 anos", 30}, new { collectionAlias = "Dos 30 acima", y = 30, selected = true } }))) </div> <div> @(Html.ShieldChart() .Name("chart2") .Theme("dark") .IsInverted(true) .Tooltip(tooltip => tooltip.AxisMarkers(axisMarkers => axisMarkers .Enabled(true) .Mode(ShieldUI.AspNetCore.Mvc.Chart.TooltipAxisMarkerMode.X) .Width(1) .ZIndex(3))) .PrimaryHeader(header => header.Text("Balanço por Semestre")) .Export(false) .AxisX(axis => axis.CategoricalValues("2016.1", "2016.2", "2017.1")) .DataSeries(series => series.Bar() .Name("Em milhares de reais") .Data(new object[] { 100, 320, 453 }))) </div> </text>)) </div>

Exceto por alguns trechos, o leitor pode perceber a semelhança, inclusive com o primeiro chart que criamos no início do artigo. A flexibilização vai além, podendo atingir até o consumo de serviços para popular os valores em vez dos fixos que vemos, cruzamento de dados, mixing entre widgets de várias formas, além de, é claro, ter todo o poder do HTML/CSS/JavaScript em mãos para mesclar com os códigos do ASP.NET Core.

É claro que quando se trata da seleção da melhor ferramenta/biblioteca de mercado, dada a quantidade expressiva de opções, a tarefa tem de ir um pouco além e analisar fatores como integração, multilinguagem, facilidade de manuseio, etc. O Shield UI consegue abraçar bem todos os cenários justamente pela flexibilidade em se desenvolver para .Net, Java, JavaScript, etc. e poder portar isso em diferentes plataformas. Todavia, é paga para propósitos comerciais e aí cabe à sua equipe/empresa analisar as condições e viabilidade mediante todos o poder que ele te dá, como vimos. Boa sorte e bons estudos!

Artigos relacionados