.NET 6  - Blazor : Componentes Dinâmicos - II


Hoje vou continuar apresentando o novo recurso Dynamic Components do Blazor disponível a partir do .NET 6.

Continuando o artigo anterior veremos como passar parâmetros para um componente dinâmico.

Blazor : Componentes dinâmicos

Vamos criar um novo projeto Blazor Server usando o template Blazor Server App:

Informe o nome Blazor_CompDinamicos ao projeto e solução e defina as configurações conforme abaixo:

Nota: Estamos usando o .NET 6.0 RC 2.

Clicando em Create teremos o projeto criado com a seguinte estrutura:

Vamos agora renderizar o componente SurveyPrompt criado por padrão na pasta Pages usando um DynamicComponent.

Para isso altere o código do componente Index.razor para:

@page "/"
<PageTitle>Index</PageTitle>
<h3>Usando DynamicComponent</h3>
Para renderizar SurveyPrompt
<DynamicComponent Type="type" />
 
@code {
    Type type = typeof(SurveyPrompt);
}

 

Executando o projeto teremos:

Vamos agora passar parâmetros para o componente SurveyPrompt.

O componente SurveyPrompt possui o parâmetro Title e assim podemos passar este parâmetro usando DynamicComponent.

Para isso vamos alterar o código do componente Index.razor para:

@page "/"
<PageTitle>Index</PageTitle>
<h3>Usando DynamicComponent</h3>
Para renderizar SurveyPrompt
<DynamicComponent Type="type" Parameters="parameters" />
 
@code {

    Type type = typeof(SurveyPrompt);

    IDictionary<string, object> parameters = new Dictionary<string, object> 
     { { "title", "Macoratti.net ->" } };
}

Executando o projeto novamente temos:

Assim passamos o parâmetro title com o valor 'Macoratti.net ->' para o componente SurveyPrompt usando um Dictionary.

DynamicComponent : Comunicação a partir de um Componente Filho(Child) para o Pai(Parent)

Quando queremos enviar uma mensagem de um componente filho para um componente pai, geralmente usamos eventos com um parâmetro do tipo EventCallback.

Isso não é uma opção com DynamicComponent, já que o parâmetro é do tipo IDictionary <string, object>, portanto não podemos passar um evento no dicionário.

Uma solução é usar parâmetros em cascata. Lembrando que com parâmetros em cascata podemos ter parâmetros que podemos usar de qualquer componente filho, sem ter que recebê-los por meio de um atributo como Parameter.

Neste caso a primeira coisa a fazer é criar uma classe que vai conter o tipo de dados a enviar no parâmetro cascade:

public class AppState
{
    public Action Action { get; set; }
    public Action<Dictionary<string, object>> ActionWithParameters { get; set; }
}

No nosso caso, estamos usando duas propriedades:

  1. Uma que possui uma Action que não recebe parâmetros;
  2. E outra que recebe parâmetros;

Aquele que recebe os parâmetros recebe um Dictionary<string, objeto>. É importante levar em consideração que esses parâmetros serão enviados do componente filho para o componente pai. Isso é útil quando queremos receber vários valores do componente filho. Também poderíamos usar uma classe para isso em vez de um dicionário, se quiséssemos.

Agora suponha que temos um componente ButtonComponent que recebe o parâmetro em cascata:

<button @onclick="handleClick">Clique aqui</button>
 
@code {
    private void handleClick()
    {
       appState.Action?.Invoke(); 
        var dictionary= new Dictionary<string, object>() { 
        { "key 1", "value 1" }, 
        { "key 2", "value 2" } };         
        appState.ActionWithParameters?.Invoke(dictionary);
    }

    [CascadingParameter] public AppState appState { get; set; }
}

Como podemos ver, este componente consiste em um botão que, ao ser clicado, executa o método handleClick. E, em handleClick o que fazemos é usar os métodos Action e ActionWithParameters e invocá-los. Note que no segundo fazemos isso passando o dicionário com os valores que queremos enviar para o componente pai.

Nota: Estamos usando Action e ActionWithParameters, a título de exemplo, provavelmente você usará apenas um de cada vez.

Agora vejamos o componente Pai em ação:

<CascadingValue Value="appState">
    <DynamicComponent Type="typeof(ButtonComponent)" />
</CascadingValue>
 
@code {

    AppState appState = new AppState();

    protected override void OnInitialized()
    {
        appState.Action = HandleClick;
        appState.ActionWithParameters = HandleClickParameters;
    } 
    private void HandleClick()
    {
        Console.WriteLine("Parent Component: Handle Click");
    } 
    private void HandleClickParameters(Dictionary<string, object> dictionaryParams)
    {
        foreach (var param in dictionaryParams)
        {
            Console.WriteLine($"{param.Key}: {param.Value}");
        }
    }
}

Neste código temos nosso DynamicComponent dentro de um CascadingValue, que usamos para enviar uma instância de appState.

Então, no método OnInitialized, incluimos os métodos que queremos que sejam executados quando o usuário clicar no botão do componente ButtonComponent.

"Quanto lhe for possível, não deixe de fazer o bem a quem dele precisa"
Provérbios 3:27


Referências:


José Carlos Macoratti