Trabalhando com ViewComponents no .NET Core

24 Nov 2018, CSHARP , .NET CORE

1011 Palavras, por José luiz

#ASP.NET Core , #ViewComponents , #Reusable View Components



ViewComponents

Intro

Olá pessoal, tudo bem ? Então, hoje eu vou falar sobre ViewComponents, este incrível recurso dentro do .NET Core (1.0, 1.1, 2.0), se você tem desenvolvido software, provavelmente você sabe sobre DRY (Don’t Repeat Yourself), e construir o aplicativo usando este conceito vai economizar o nosso tempo!



Então eu vou mostrar para vocês como transformar uma parte do seu código em Componente e reusar em qualquer parte da sua aplicação.

Nos vamos criar 3 tipos de ViewComponents e um conteúdo extra!!

  1. Simples HTML Leia para entender os conceitos básicos..;)
  2. Lista Fixa
  3. Componentes Lendo do banco de dados
  4. Refresh Components com Javascript

Como você sabe, eu tento escrever bastante sobre o assunto, então tenha uma boa leitura

Simples HTML

Este é o básico sobre ViemComponents ok?
Primeiro vamos criar um novo projeto usando a linha de comando:

dotnet new mvc --name NetCoreComponent --auth Individual

E checkar se está tudo ok com a linha de comando:

dotnet run

Depois vamos navegar no endereço localhost:

Home Page É somente nossa página, nada de mais ainda.

Agora vamos criar um simples ViewComponents apenas retornand um HTML contendo algum mensagem para nosso usuário.

Estou usando Visual Studio Code.. :)

  1. Crie uma pasta chamada Components para organizar nosso código
  2. Crie uma classe chamada “Simple.cs” dentro desta pasta
  3. Crie um arquivo CSHTML (veja mais abaixo)

código da class

using Microsoft.AspNetCore.Mvc;
namespace NetCoreComponent.Components
{
    public class Simple : ViewComponent
    {
        public IViewComponentResult Invoke()
        {
            return View();
        }
    }
}

Todo Componente:

  • Precisa herdar da ViewComponent (Você pode criar usando decorations ou somente usando sufixo ViewComponent)
  • Tem suporte ao DI (Dependency Injection )
  • Preciso conter o método IViewComponentResult Invoke() ou IViewComponentResult InvokeAsync()
  • Precis ter um arquvo CSHTML

Não é possível usar filtros em ViewComponents IPageFilter ou IAsyncPageFilter


Nós precismao criar nosso CSHTML, então você pode usar umas destas pastas:

  • /Pages/Components/{View Component Name}/{View Name}
  • /Views/{Controller Name}/Components/{View Component Name}/{View Name}
  • /Views/Shared/Components/{View Component Name}/{View Name}

O nome default da view para a ViewComponent é Default.cshtml.

Eu gosto de criaar minhas Views em “Views/Shared/Components/{View Component Name}/Default.cshtml”.
Nosso componente deve ficar em:

Views/Shared/Components/Simple/Default.cshtml

E nosso código:

<h1>Simple Component HTML</h1>
<p>Hello, please don't forget to send a message... :)</p>
<ul>
  <li>list 1</li>
  <li>list 2</li>
  <li>list 3</li>
</ul>


Invocando noosso ViewComponent

Para usar nossa view component, vamos chamar usando o código abaixo

@await Component.InvokeAsync("Simple")

Mas é melhor usar a Tag Helper então aadicione “@addTagHelper *, NetCoreComponent” nos arquivos cshtml que deseja usar a ViewComponents, porém (Adicione em “_ViewImports” pois habilitará o uso em qualquer View), Depois você pode chamar assim:

”@addTagHelper *,

<vc:simple></vc:simple>

Agora nossa aplicação consegue renderizar nosso componente;


Agora que sabemos o básico, vamos criar algo mais interessante.

Lista Fixa

Para este ViewComponent vamos criar outra classe chaaada Todo.cs:

using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;

namespace NetCoreComponent.Components
{
    public class Todo : ViewComponent
    {
        public IViewComponentResult Invoke()
        {
            return View(new List<string>() { "First", "Second", "Thirth", "Fourth" });
        }
    }
}

O ponto aqui é passar informação do ViewComponents para a View, então vamos criar nosso CSHTML na pasta:
“Views/Shared/Components/Todo/Default.cshtml”
Com este código:

@model IEnumerable<string>
  <h1>Fix List</h1>
  <ul>
    @foreach (var item in Model) {
    <li>@item</li>
    }
  </ul>
</string>

E finalmente chamar em nossa index.cshtml:

<vc:todo></vc:todo>

Reiniciando nossa aplicação:

É possível passar qualquer infromação do Componente para a View e é possível usar parametros normalemente:

Mude a classe e adiciona o parâmetro str

using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;

namespace NetCoreComponent.Components
{
    public class Todo : ViewComponent
    {
        public IViewComponentResult Invoke(string str)
        {
            string[] all = str.Split(new char[] { ';' });
            return View(all);
        }
    }
}

Para passar os parâmetros use desta forma:

<vc:todo str="The;View;Its;Amazing"></vc:todo>

Reinicie a aplicação:


Ok, vamos parar de brincar aqui, vamos integrar com Banco de Dados!
Para isso eu esotu usando MariaDB, se você não sabe como integrar MariaDB com .NET Core, leia isso


Componentes Lendo do banco de dados

Nesta ViewComponents vamos criar outra classe chamada TodoDB.cs com este código: Veja vamos usar o método InvokeAsync Sim, usaremos async… com parâmetros

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NetCoreComponent.Data;
using NetCoreComponent.Models;

namespace NetCoreComponent.Components
{

    public class TodoDb : ViewComponent
    {
        private readonly ApplicationDbContext db;

        public TodoDb(ApplicationDbContext context) => this.db = context;

        public async Task<IViewComponentResult> InvokeAsync(bool done)
        {
            var items = await GetItemsAsync(done);
            return View(items);
        }

        private Task<List<TodoList>> GetItemsAsync(bool done)
        {
           db.TodoList.Where(a => a.done == done).ToListAsync();
        }
    }
}

O ponto aqui é mostrar usando Components com banco de dados, então vamos criar nosso CSHTml:
Views/Shared/Components/TodoDB/Default.cshtml.
Com este código

@model IEnumerable<TodoList>
  <h1>My Todo List DB</h1>
  <ul>
    @foreach (var item in Model) {
    <li>@item.task</li>
    }
  </ul>
</TodoList>

E finalmente chamar em nosso arquivo index.cshtml:

<vc:todo-db done="true"></vc:todo-db>

O nome do nosso componente é ‘TodoDb’, então por cause do CamelCase, nós precisamosmudar ’D’ for ‘-d’, se nosso componente chamasse ‘TodoWithCommercial’ então chamaríamos assim ‘vc:todo-with-commercial’

Reinicie a aplicação

Apenas para checkar no banco de dados

Ok, E se precisarmos fazer um refresh via javascript?

Refresh Components com Javascript

Eu criei um arquivo simples Javascript para este propósito, primeiro crie um botão na página index.cshtml com a class update. parecido com:

<button class="update">Update</button>
<div class="row todo">
  <vc:todo-db done="true"></vc:todo-db>
</div>

Para atualizar, precisamos criar um método no nosso Home Controller, então veja como ficou, veja que neste caso estamos chamando o componente pelo nome exato;

    public IActionResult UpdateTodoList(bool done)
    {
        object paramets = new { done = done };
        return ViewComponent("TodoDb", paramets);
    }

criand e importando o javascript:

let btn = document.querySelector(".update");
let divEle = document.querySelector(".todo");

   btn.addEventListener("click", (e) => {
  e.preventDefault();

  let url = "/Home/UpdateTodoList?done=true";
  divEle.innerHTML = "Update...";
  btn.disabled = true;

  var xhr = new XMLHttpRequest();
  xhr.open("GET", url, true);

  xhr.addEventListener("load", () => {
    if (xhr.status === 200) {
      divEle.innerHTML = xhr.responseText;
      btn.disabled = false;
    }
  });

  setTimeout(() => xhr.send(), 1500);

});

Terminamos, agora nós podemos efetuar um update nos dados do Componente!

Sim, eu coloquei another via database e somente cliquei no botão.. :)

Conclusão

Trabalhar com ViewComponents é muito fácil e interessante para assegurar que não repetiremos códigos em nossa aplicação, e com certeza deixaremos nosso código mais extensível e resutilisável.

Eu tenho trabalhado com ViewComponents e estou muito feliz com os resultados.
O link para o projeto está no GitHub, de uma olhada nele
Project

Note...

Olá, meu nome é José Luiz e você sabe meu compromisso com você - sem post pagos, sem anuncios, sem conteúdo privado, somente post.

Se você curtiu esta produção, por favor, considere me enviar um cafézinho para apoiar o que eu faço...

Me pague um café e ajude o mundo!

Toda contribuição é enviada para MSF & O Bem nunca para :)