Blazor: Razor component inherited parameter of base class not set

epanalepsis picture epanalepsis · Feb 17, 2020 · Viewed 7.5k times · Source

I've got a problem with one of my razor component libraries.

I've got an abstract base class RazorHtmlComponent for my components with a parameter property [Parameter] public string InlineClass { get; set; } which shall be used for css classes to be mapped to the actual component. Then I've got another base class per component containing the component specific properties which is definined like this: abstract class BaseRazorButton: RazorHtmlComponent

My component, in this example RazorButton.razor inherits from the abstract button base class BaseRazorButton.

The problem is, when I instantiate a razor button, and I set the property InlineClass to any value, it stays null within my actual RazorButton instance.

Here's a minimal code example for better understanding:

Base class:

public abstract class RazorHtmlComponent : ComponentBase, IRazorHtmlComponent
{
  [Parameter] public string InlineClass { get; set; }

  public DomDefinitionMapper ClassMapper { get; }

  ...

  protected RazorHtmlComponent()
  {
    ClassMapper = new DomDefinitionMapper(InlineClass);
  }

Dom definition mapper:

  public class DomDefinitionMapper
  {
    public List<Func<string>> DefinitionRepository { get; } = new List<Func<string>>();

    public DomDefinitionMapper(string definition = "")
    {
      if (!string.IsNullOrEmpty(definition))
      {
        DefinitionRepository.Add(() => definition);
      }
    }

    public string GetDefinitions(char separator = default)
      => separator.Equals(default) ? 
          string.Join(" ", DefinitionRepository.Select(i => i()).Where(i => i != null)) 
        : string.Join($" {separator}", DefinitionRepository.Select(i => i()).Where(i => i != null));
  }

Button base class:

public abstract class BaseRazorButton: RazorHtmlComponent
{
  ...
}

Razor button component:

@inherits BaseRazorButton

<button class="@ClassMapper.GetDefinitions()">
  @Text
</button>

Instantiation of a Razor button:

<RazorButton InlineClass="page" 
             Text="1"/>

When I inspect within in the browse, the class "page" defined within using the InlineClass parameter is not set. In debug mode, the ClassMapper DefinitionRepository does not contain the class.

Am I missing something? I just don't understand why it doesn't work :/

Answer

agua from mars picture agua from mars · Feb 17, 2020

If you call that in the construtor :

[Parameter] public string InlineClass { get; set; }
...
protected RazorHtmlComponent()
{
    ClassMapper = new DomDefinitionMapper(InlineClass);
}

The parameter is not yet set. It'll be when OnInitialized or OnInitializedAsync is called.
And your RazorHtmlComponent must derived from ComponentBase

public abstract class RazorHtmlComponent : ComponentBase, IRazorHtmlComponent
{
  [Parameter] public string InlineClass { get; set; }

  public DomDefinitionMapper ClassMapper { get; }

  ...

  protected override void OnInitialized()
  {
    ClassMapper = new DomDefinitionMapper(InlineClass);
  }