Componentes no Blazor: utilizando RenderFragments

Componentes no Blazor: utilizando RenderFragments

O uso de componentes nos permite criar blocos de código, com aparência e comportamento, que podem ser reutilizados em toda a aplicação, garantindo praticidade e consistência no código e na experiência de uso.

No Blazor é possível criar componentes para atender as mais variadas demandas, inclusive recebendo parâmetros e expondo eventos. Porém, às vezes temos a necessidade de não apenas passar parâmetros para os componentes, como também adicionar blocos de código HTML e mesmo outros componentes em seu interior. Para estes casos utilizamos os RenderFragments, que são blocos de código que podem ser inseridos dentro dos componentes, como parte de seu conteúdo.

Neste artigo veremos como utilizar os RenderFragments, tanto em sua abordagem mais simples, contendo apenas uma instância desse bloco, como também na forma mais completa, com vários fragmentos em um mesmo componente.

Criando o projeto

Para as demonstrações que faremos neste artigo, criaremos um projeto Blazor padrão com o template Blazor Web App. Para isso, você pode executar o seguinte comando em seu terminal, utilizando a .NET CLI:

				
					dotnet new blazor --name ComponentesBlazor
				
			

Esse comando criará o projeto de nome ComponentesBlazor utilizando o modo de interatividade InteractiveServer por página/componente.

Caso esteja utilizando o Visual Studio, você pode utilizar a opção “Create new project” e selecionar o template “Blazor Web App”, como mostra a imagem abaixo:

Na página seguinte, dê o nome desejado ao projeto e clique em Next. E na próxima tela, basta manter os valores padrão, como na imagem abaixo. A diferença aqui é que por padrão a interatividade será global, mas para este exemplo, as duas opções funcionarão igualmente:

Depois, basta clicar em Create e executar o projeto, que deve gerar o seguinte resultado:

 

Como exemplo criaremos um componente chamado Painel, que fará o papel de um container genérico de conteúdo, podendo conter um título e um corpo com outros elementos HTML.

Adicionando o componente

Para criar o componente, vamos adicionar dentro da pasta Components um novo arquivo chamado Painel.razor e definiremos seu conteúdo de acordo com o código abaixo:

				
					<div class="border border-2 border-dark rounded p-2">
    @if(!string.IsNullOrWhiteSpace(Titulo))
    {
        <h1>@Titulo</h1>
        <hr />
    }
</div>

@code {
    [Parameter]
    public string? Titulo { get; set; }
}

				
			

Aqui estamos criando uma div com algumas classes do Bootstrap, que é adicionado por padrão quando criamos o projeto. Em seu interior adicionamos um título <h1> com o conteúdo recebido no parâmetro Titulo. E como este valor é opcional, verificamos se o parâmetro não é nulo ou vazio, para só exibi-lo se for realmente necessário.

Agora, no arquivo Home.razor, vamos substituir seu conteúdo pelo seguinte:

				
					<Painel Titulo="Componentes no Blazor"></Painel>
				
			

Como criamos o componente no mesmo nível da página Home, não é necessário adicionar nenhum using. Se você criou em uma pasta diferente, provavelmente precisará adicionar a diretiva using importando o namespace no qual seu componente se encontra.

Ao executarmos o projeto agora, temos o resultado abaixo:

Conforme definimos, temos aqui a div com o título sendo exibidos. Esta é estrutura básica de um componente que depende apenas de parâmetros para funcionar. Todo o conteúdo HTML é definido internamente, sem possibilidade de edição para quem o está utilizando.

Utilizando ChildContent

Partindo do nosso componente Painel criado anteriormente, vamos agora adicionar a ele a possibilidade de ter seu conteúdo definido pelo seu utilizador. Ou seja, quando usarmos esse componente na página Home, deveremos ser capazes de definir não apenas seu título, mas também o corpo do painel, adicionando outros elementos HTML.

Para que isso seja possível, vamos utilizar a classe RenderFragment e declarar  no componente Painel uma propriedade chamada ChildContent. Este nome é obrigatório para obter o resultado que desejamos no momento. E no código HTML, vamos renderizar o conteúdo dessa propriedade:

				
					<div class="border border-2 border-dark rounded p-2">
    @if(!string.IsNullOrWhiteSpace(Titulo))
    {
        <h1>@Titulo</h1>
        <hr />
    }
    @ChildContent
</div>

@code {
    [Parameter]
    public string? Titulo { get; set; }
    [Parameter]
    public RenderFragment? ChildContent{ get; set; }
}

				
			

Voltando agora no arquivo Home.razor já seremos capazes de adicionar conteúdo no painel que criamos anteriomente:

				
					<Painel Titulo="Componentes no Blazor">
    <div class="alert alert-info">
        Conteúdo do painel
    </div>
</Painel>
				
			

O resultado agora é este:

Observe que não foi preciso utilizar nome de parâmetro para adicionar conteúdo ao painel na home. Isso ocorre porque declaramos o RenderFragment com o nome ChildContent. Quando fazemos isso, todo conteúdo HTML contido entre as tags de abertura e fechamento do componente são automaticamente coletadas por essa propriedade.

Utilizando múltiplos RenderFragments

Apesar de um único RenderFragment suprir a demanda de boa parte dos componentes, existem casos em que precisamos renderizar várias “seções” em um mesmo componente.

Neste caso, podemos utilizar múltiplos RenderFragments, e ao utilizá-los basta delimitar seu conteúdo por meio de tags. Voltando ao arquivo Painel.razor, vamos substituir o código anterior:

				
					<div class="border border-2 border-dark rounded p-2">
    @if(Cabecalho is not null)
    {
        <div class="border border-2 bg-light border-dark rounded p-2 mb-2">
            @Cabecalho
        </div>
    }

    @if (Corpo is not null)
    {
        <div class="border border-2 border-dark rounded p-2">
            @Corpo
        </div>
    }

    @if(Rodape is not null)
    {
        <div class="border border-2 bg-light border-dark rounded p-2 mt-2">
            @Rodape
        </div>
    }
</div>

@code {
    [Parameter]
    public RenderFragment? Cabecalho { get; set; }
    [Parameter]
    public RenderFragment? Corpo { get; set; }
    [Parameter]
    public RenderFragment? Rodape { get; set; }
}

				
			

Dessa vez temos três RenderFragments, nomeados como Cabecalho, Corpo e Rodape. Cada um deles é renderizado no interior do painel com suas formataçãoes visuais específicas utilizando Bootstrap. Agora o utilizador deste componente tem a liberdade de definir o conteúdo dessas três seções separadamente.

Apesar de neste exemplo termos removido o parâmetro Titulo, você pode mantê-lo e mesmo adicionar outros livremente. Basta definir a lógica de utilização de cada parâmetro, incluindo os RenderFragments.

Por fim, vamos voltar à home e alterar a forma de uso do painel:

				
					<Painel>
    <Cabecalho>
        <span>Cabeçalho do painel</span>
    </Cabecalho>
    <Corpo>
        <p>Conteúdo do painel</p>
    </Corpo>
    <Rodape>
        <span>Rodapé do painel</span>
    </Rodape>
</Painel>
				
			

O resultado dessa alteração deve ser semelhante ao que mostra a figura abaixo:

Como todos os fragmentos são opcionais e fizemos o devido tratamento para cada um, temos a flexibilidade de utilizar apenas os que desejarmos. Por exemplo, se precisarmos apenas do corpo do painel, podemos fazer:

				
					<Painel>
    <Corpo>
        <p>Conteúdo do painel</p>
        <p>Conteúdo do painel</p>
        <p>Conteúdo do painel</p>
    </Corpo>
</Painel>
				
			

E o resultado continuará consistente dentro da nossa proposta:

Acelere a sua carreira conosco!

Se você é Desenvolvedor .NET Júnior e quer acelerar sua carreira até nível Pleno com salário de R$7k+, ou mesmo busca a primeira vaga, conheça a Mentoria .NET Start: Clique aqui

Se é Desenvolvedor .NET Pleno ou Sênior e quer virar referência técnica em sua equipe e mercado, com salário de R$10k+, conheça a Mentoria .NET Expert: Clique aqui

Conclusão

O uso de um ou mais RenderFragments nos dá a possibilidade de customizar o uso, aparência e conteúdo de alguns componentes. Ao oferecer essa possibilidade para o utilizador, é importante garantir a consistência do funcionamento diante dos variados cenários que o componente suporta, garantindo uma boa experiência para o programador e para o usuário final.

Partindo do conhecimento adquirido neste artigo, você poderá unir os parâmetros de tipos nativos e complexos, como strings, números e enums com os RenderFragments, e oferecer soluções flexíveis e robustas de componentização em seus projetos.