Criando um Componente de Tabs no Blazor

Nesse artigo veremos como criar um componente de Tabs com o Blazor. Para melhor entender esse artigo, sugiro que você dê uma olhada nos seguintes Tópicos:

Plano

A ideia é implementarmos a funcionalidade de Tabs com o Blazor. Ou seja, criar um componente que nos permita apresentar conteúdo separado por Tabs (ou Abas).

Na verdade, para alcançar esse objetivo precisaremos criar dois componentes, e não apenas um. Criaremos um componente chamado TabSet.razor, que representará um determinado conjunto de Tabs. E para representar uma Tab dentro do TabSet, vamos criar o componente Tab.razor.

Sendo assim, o componente TabeSet deverá permitir que adicionemos ao seu conteúdo, vários componentes Tab.

Dois conceitos são importantes para alcançarmos esse objetivo. Primeiramente você precisa conhecer o recurso  ChildContent, que será utilizado nos dois componentes que serão criados.

E em segundo lugar, você precisa entender como funciona o CascadingValue e o CascadingParameter. Esses elementos são utilizados quando precisamos passar valores de um componente Pai para um componente Filho. E nesse exemplo, como veremos adiante, teremos um cenário desse.

ITab

Para começar, precisamos definir uma interface para representar uma Tab. Essa interface será útil para escrevermos o comportamento das Tabs no componente TabSet.razor. Sendo assim, crie essa interface como nos mostra a Figura 1.

Figura 1: Interface ITab que representa um item do TabSet

Veja que a interface define apenas a propriedade ChildContent, que o TabSet vai precisar para poder renderizar o conteúdo da Tab Selecionada.

TabSet

Agora que já temos uma representação para uma Tab com o ITab, vamos partir para a codificação do componente TabSet.razor. Comece importando o namespace onde você criou o ITab, como mostra a Figura 2.

Figura 2: Importando namespace da interface ITab

Em seguida vamos partir para as propriedades que precisamos criar nesse componente. Veja na Figura 3 que precisamos de 2 propriedades.

Figura 3: Propriedades do componente TabSet

Note que temos uma propriedade para representar o Parâmetro ChildContent, onde serão renderizados os títulos das Tabs. E uma outra propriedade chamada TabAtiva do tipo ITab.

Essa segunda propriedade servirá justamente para termos uma referência à Tab que for selecionada pelo usuário.

Com isso já podemos desenhar a interface HTML do componente TabSet. Veja como ele deve ser implementado na Figura 4.

Figura 4: HTML do Componente TabSet

Como você pode ver, estamos usando um CascadingValue para passar uma referência do TabSet, para todos as Tabs que forem inclusas nele. Isso é necessário para que um Tab possa “avisar” o TabSet quando ele for selecionado.

Veja também que dentro do CascadingValue vamosrenderizar o ChildContent do TabSet. O ChildContent do TabSet vai conter apenas os títulos das Tabs. Você verá isso mais claramente na implementação do Tab.

Já no corpo do TabSet iremos renderizar o ChildContent do componente Tab que estiver selecionado, representado aqui pela propriedade TabAtiva.

Para finalizar a implementação do TabSet, precisamos implementar os métodos que serão usados para definir qual é a Tab Selecionada. São dois métodos, que você poder ver na Figura 5.

Figura 5: Métodos AddTab e SelecionaTab

Esses dois métodos serão utilizados pelas Tabs que forem adicionadas ao TabSet. O principal é o método SelecionaTab, que recebe a tab por parâmetro. Caso a tab não esteja ativa, o método atribui o parâmetro tab à propriedade TabAtiva.

O método StateHasChanged é necessário para que o conteúdo do componente Tab seja devidamente renderizado no corpo do TabSet.

Já o método AddTab serve apenas para definir qual será a Tab que inicialmente estará selecionada. Como você pode ver pela lógica do método, a primeira Tab adicionada ao TabSet será definida como TabAtiva.

Tab

Com o TabSet devidamente implementado, já podemos começar a codificar o componente Tab. Vamos começar importando o namespace do ITab, e definindo que o componente Tab implementa essa interface. Veja Figura 6.

Figura 6: Importando namespace e implementado interface

Em seguida nós vamos definir os parâmetros e propriedades do Componente. Confira na Figura 7.

Figura 7: Parâmetros e Propriedades do componente Tab

Temos dois parâmetros no componente Tab, o Título da Tab e o seu ChildContent. O ChildContent é o conteúdo da Tab e será renderizado pelo TabSet, quando a Tab estiver ativa.

A propriedade TabSet é do tipo CascadingParameter, e ela será atribuída por cascata pelo TabSet. Veja que usamos o TabSet na propriedade TituloCss, para definir se iremos renderizar a classe css active no título da Tab, indicando assim que ela está selecionada.

Veja na Figura 8 como fica o HTML desse componente.

Figura 8: HTML do Componente Tab

Como você pode ver, o componente Tab renderiza apenas o seu título, e deixa para o TabSet a renderização do seu ChildContent. Como já foi dito, a propriedade TituloCss é usada para aplicar a css active quando a Tab for selecionada.

Note que o título é criado com um link através da tag <a />. E no evento onclick dessa tag estamos chamando o método Selecionar. Veja na Figura 9 a implementação deste e de outro método necessário no componente Tab.

Figura 9: Métodos do componente Tab

O primeiro método da Figura 9 é o OnInit. Esse método é sobrecarregado da classe base do componente e é executado na sua inicialização. Aproveitamos esse método apara chamar o método AddTab do TabSet, e com isso, definir que a primeira Tab do TabSet iniciará como a TabAtiva.

Já o método Selecionar será executado pelo click no título da Tab, e irá chamar o método SelecionaTab do TabSet. Com isso você pode ver a importância da referência do TabSet passada por cascata do componente pai para os seus filhos.

Testando

Para testarmos o TabSet e o Tab, vamos incluir esses componentes no Index.razor do nosso projeto de exemplo.

Como você pode ver na Figura 10, devemos incluir a tag TabSet no HTML, e dentro dessa tag vamos adicionando os componentes Tab.

Figura 10: Usando componentes TabSet e Tab

Foram inclusas três Tabs no TabSet. Cada Tab recebeu um Título e um Conteúdo (ChildContent). Para o conteúdo dos Tabs podemos incluir o HTML que quisermos, inclusive outros componentes da nossa aplicação, como você pode conferir no terceiro Tab.

Execute o seu projeto e veja o resultado do nosso TabSet, aqui na Figura 11.

Figura 11: Executando o Exemplo do TabSet com 3 Tabs

Como você pode ver a nossa implementação de TabSet funciona perfeitamente. Veja que utilizamos os recursos de css do bootstrap para estilizar o nosso componente. Seguindo esse exemplo você pode implementar o seu componente de Tab com as funcionalidades que quiser.

Grande Abraço e até o próximo!