I had no idea how to phrase a good title here.
I'm basically trying to use the open-closed principle, so I don't need to specify precisely which component to render, but just use an interface/abstract class instead.
I'm making a node editor. I have a List of NodeModelBases, to hold the data for each node, and for each of these, I want to insert a corresponding NodeComponent to be rendered. Currently:
<div class="diagram-html-layer">
@foreach (NodeModelBase node in nodeModelManager.Nodes) {
<NodeBase NodeModel="@node" OnDeleteEvent="OnDeleteNode"/>
}
</div>
The idea is that NodeModelBase is inherited by specific types of Nodes, so I could have a "StartNode : NodeModelBase", "DelayNode : NodeModelBase" , etc., i.e. sub-classes of NodeModelBase. I may potentially have 20 or more sub-classes, and I would like to not update the above for-loop for each new added node type.
I then want to render their respective component. Currently, I have a Blazor component called NodeBase, which I just insert, because I only have one node type so far. But I would like to be able to do something like: node.GetHTML() and insert this instead.
I could have a long if-else to check which sub-class of NodeModelBase I have, and then insert the correct component, something like:
if(node is StartNode) {
<StartNode/>
} else if (node is DelayNode) {
<DelayNode/>
} else ...
But that's pretty inconvenient.
I know this can be done programmatically by using the RenderTreeBuilder, and making calls like builder.OpenElement(...), or builder.AddAttribute(...), so the result would look something like:
<div class="diagram-html-layer">
@foreach (NodeModelBase node in nodeModelManager.Nodes) {
@node.GetRenderFragment();
}
</div>
But being a html/blazor novice, I would much prefer to be able to define the html/razor syntax normally, and somehow return/insert that.
So, any suggestions on how to be flexible about which component is inserted?