Say I have a component MyComponent
that prints out this HTML:
<my-component attr1="@(Attr1)"
attr2="@(Attr2)"
@attributes="@(AdditionalAttributes)">
@(ChildContent)
</my-component>
Now I want to have MoreDetailedComponent
that inherits MyComponent
and declares Attr3
. Can I reuse the above code somehow so I do not have to rewrite it (in reality there are tens of them):
@inherits MyComponent
<my-component attr1="@(Attr1)"
attr2="@(Attr2)"
attr3="@(Attr3)"
@attributes="@(AdditionalAttributes)">
@(ChildContent)
</my-component>
Turn out it's very simple, I just extend the AdditionalAttributes
like this:
// Non-extendable components
public class DefaultMdComponent : ComponentBase
{
[Parameter(CaptureUnmatchedValues = true)]
public IEnumerable<KeyValuePair<string, object>>? AdditionalAttributes { get; set; }
[Parameter]
public RenderFragment? ChildContent { get; set; }
}
// Extendable components should inherit this
public class DefaultInheritableComponent : DefaultMdComponent
{
protected virtual IEnumerable<KeyValuePair<string, object>>? ProtectedAdditionalAttributes
=> null;
protected IEnumerable<KeyValuePair<string, object>>? FinalAdditionalAttributes
{
get
{
if (AdditionalAttributes is null) { return ProtectedAdditionalAttributes; }
if (ProtectedAdditionalAttributes is null) { return AdditionalAttributes; }
return AdditionalAttributes.Concat(ProtectedAdditionalAttributes);
}
}
}
MyComponent
should prints it out like this:
<my-component attr1="@(Attr1)"
attr2="@(Attr2)"
@attributes="@(FinalAdditionalAttributes)">
@(ChildContent)
</my-component>
MoreDetailedComponent
does not need its own Razor file but instead just override ProtectedAdditionalAttributes
:
public class MoreDetailedComponent : MyComponent
{
// ...
protected override IEnumerable<KeyValuePair<string, object>>? ProtectedAdditionalAttributes =>
new KeyValuePair<string, object>[]
{
new("attr3", Attr3)
};
}