Blazor - Criando um quadro Kanban - II
Neste artigo vamos continuar apresentando conceitos importantes relacionados com o tratamento de eventos no Blazor e a seguir vamos criar uma aplicação simples que simula um quadro Kanban. |
Continuando o
artigo anterior vamos criar o projeto Blazor
WebAssembly KanbanBoard.
Criando o projeto WebAssembly
Abra o VS 2022 Community e acione a opção Create New Project selecionando o template Blazor WebAssembly App infomando o nome KanbanBoard;
A seguir defina as configurações do projeto conforme mostra a figura abaixo:
Clique no botão Create para criar o projeto.
Podemos remover do projeto os componentes FetchData.razor e Counter.razor e suas dependências deixando apenas o componente Index.razor na pasta Pages.
Vamos criar no projeto a pasta Models onde vamos definir a classe TaskItem que representa o nosso domínio e a enumeração TaskPriority que define 3 níveis de prioridade.
1- TaskItem
public class TaskItem
{
public string? TaskName { get; set; }
public TaskPriority Priority { get; set; }
}
|
2- TaskPriority
public enum TaskPriority
{
High,
Mid ,
Low
}
|
Agora vamos alterar o código do componente MainLayout.razor conforme abaixo:
<main class="container">
@Body
</main>
|
Este código adiciona um contêiner ao redor do corpo da página. Neste projeto, usaremos o sistema de grade do Bootstrap para definir o layout do nosso conteúdo. Ele se baseia em uma série de contêineres, linhas e colunas. Adicionaremos as linhas e colunas mais tarde.
Criando o componente DropZone
Vamos criar na pasta Shared do projeto o componente razor DropZone que vamos usar para criar os quadros kanban no projeto. Neste componente vamos poder arrastar e soltar as tarefas entre os 3 quadros kanban que iremos criar.
@using KanbanBoard.Models
<div class="col">
<h2 style="">@Priority.ToString() Prioridade</h2>
<div class="dropzone"
ondragover="event.preventDefault();"
@ondrop="OnDropHandler">
@foreach (var item in TaskItems
.Where(q => q.Priority == Priority))
{
<div class="draggable"
draggable="true"
@ondragstart="@(() => OnDragStartHandler(item))"> @item.TaskName
<span class="badge text-bg-secondary">
@item.Priority
</span>
</div>
}
</div>
</div>
@code
{
[Parameter]
public List<TaskItem> TaskItems { get; set; } = new();
[Parameter]
public TaskPriority Priority { get; set; }
[Parameter]
public EventCallback<TaskPriority> OnDrop { get; set; }
[Parameter]
public EventCallback<TaskItem> OnStartDrag { get; set; }
private void OnDropHandler()
{
OnDrop.InvokeAsync(Priority);
}
private void OnDragStartHandler(TaskItem task)
{
OnStartDrag.InvokeAsync(task);
}
}
|
Neste código vamos usar os recursos do drag and drop ou seja arrastar e soltar:
Estamos definindo o componente Dropzone por sua prioridade e permitindo que os elementos sejam jogados nele, evitando o valor padrão do evento ondragover.
O método OnDropHandler é chamado quando um elemento é solto no Dropzone, e, por fim, ele percorre todos os itens da classe TaskItems com a Prioridade correspondente.
O parâmetro TaskItems é usado para acompanhar as tarefas que foram descartadas no Dropzone e o parâmetro Priority é usado para indicar a prioridade das tarefas que estão no Dropzone.
O evento OnDrop indica o evento que é invocado quando uma tarefa for solta no Dropzone e o evento OnStartDrag indica o evento que é invocado quando uma tarefa é arrastada do Dropzone.
Vamos agora definir um estilo associado a este componente criando o arquivo Dropzone.razor.css :
.draggable {
margin-bottom: 10px;
padding: 10px 25px;
border: 1px solid #424d5c;
background: #ff6a00;
color: #ffffff;
border-radius: 5px;
cursor: grab;
}
.draggable:active {
cursor: grabbing;
}
.dropzone {
padding: .75rem;
border: 2px solid black;
min-height: 20rem;
}
|
Criando o componente NewTask
Vamos criar na pasta Shared do projeto o componente razor NewTask que permite incluir novas tarefas no quadro Kanban.
<div class="row pt-3" >
<div class="input-group mb-3">
<label class="input-group-text"
for="inputTask">
Tarefa
</label>
<input @ref="taskInput"
type="text"
id="inputTask"
class="form-control"
@bind-value="@taskName"
@attributes="InputParameters" />
<button type="button"
class="btn btn-outline-secondary"
@onclick="OnClickHandlerAsync">
Incluir tarefa
</button>
</div>
</div>
@code{
private string? taskName;
private ElementReference taskInput;
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object>?
InputParameters{ get; set; }
[Parameter]
public EventCallback<string> OnSubmit { get; set; }
private async Task OnClickHandlerAsync()
{
if (!string.IsNullOrWhiteSpace(taskName))
{
await OnSubmit.InvokeAsync(taskName);
taskName = null;
await taskInput.FocusAsync();
}
}
}
|
No código deste componente temos :
A inclusão de uma Label, uma caixa de texto e um button. Onde a caixa de texto inclui um atributo @ref que usaremos mais tarde para definir o foco para a caixa de texto.
A seguir invocamos o método OnSubmit, definimos o campo taskName como nulo e colocamos o foco para o objeto taskInput usando o método FocusAsync.
Usando os componentes criados
Vamos agora usar os componentes DropZone e NewTask que foram criados alterando o código do componente Index.razor na pasta Pages.
@page "/"
<PageTitle>Quadro Kanban</PageTitle>
<NewTask OnSubmit="AddTask"
@attributes="InputAttributes" />
<div class="row">
<Dropzone Priority="TaskPriority.High"
TaskItems="TaskItems"
OnDrop="OnDrop"
OnStartDrag="OnStartDrag" />
<Dropzone Priority="TaskPriority.Mid"
TaskItems="TaskItems"
OnDrop="OnDrop"
OnStartDrag="OnStartDrag" />
<Dropzone Priority="TaskPriority.Low"
TaskItems="TaskItems"
OnDrop="OnDrop"
OnStartDrag="OnStartDrag" />
</div>
@code {
public TaskItem? CurrentItem;
List<TaskItem> TaskItems = new();
protected override void OnInitialized()
{
TaskItems.Add(new TaskItem
{
TaskName = "Revisar código",
Priority = TaskPriority.High
});
TaskItems.Add(new TaskItem
{
TaskName = "Ler livro",
Priority = TaskPriority.Mid
});
TaskItems.Add(new TaskItem
{
TaskName = "Exercício",
Priority = TaskPriority.Low
});
}
private void OnStartDrag(TaskItem item)
{
CurrentItem = item;
}
private void OnDrop(TaskPriority priority)
{
CurrentItem!.Priority = priority;
}
public Dictionary<string, object> InputAttributes = new ()
{
{ "maxlength", "25" },
{ "placeholder", "Nova tarefa" },
{ "title", "Aqui você inclui novas tarefas." }
};
private void AddTask(string taskName)
{
var taskItem = new TaskItem()
{
TaskName = taskName,
Priority = TaskPriority.High
};
TaskItems.Add(taskItem);
}
}
|
Vamos entender o código acima:
Estamos usando o componente NewTask para apresentara a caixa de entrada onde o usuário vai informar o nome da tarefa usando os recursos do attribute splatting.
A seguir estamos adicionando três componentes DropZone um para cada prioridade.
No bloco de código estamos inicializando 3 tarefas , cada uma com prioridade diferente.
No evento OnstartDrag definimos o valor de CurrentItem para o item que está sendo arrastado no momento. Usaremos esse valor quando o item for subseqüentemente descartado. O componente Dropzone invoca este método quando o evento @ondragstart é acionado.
No evento
OnDrop definios a propriedade
Priority do CurrentItem para a prioridade
associada ao Dropzone no qual ele é solto. O componente Dropzone invoca este
método quando o evento @ondrop for acionado.
Usamos a classe Dictionary para definir as
propriedades de Inputattributes.
No método AddTask definimos a prioridade do novo item como High e adicionamos a tarefa ao objeto TaskItems.
Executando o projeto iremos obter o seguinte resultado:
Pegue o código do projeto aqui : KanbanBoard.zip ...
"Regozijai-vos sempre.
Orai sem cessar.
Em
tudo dai graças, porque esta é a vontade de Deus em Cristo Jesus para convosco."
1 Tessalonicenses
5:16-18
Referências:
NET - Unit of Work - Padrão Unidade de ...