kidshaw
kidshaw

Reputation: 3451

Content out of order in Blazor when using the MarkupString

I'm trying to build a component to wrap up display of content in different html elements (TD or TH).

In this simplified example, I have two MarkupString casts from string methods with a content included between them...

@((MarkupString)GetStartingMarkup())
@GetContent()
<span>Inner Content</span>
@((MarkupString)GetEndingMarkup())

@code {

    private string GetStartingMarkup(){
        return "<span class=\"example\">";
    }

    private string GetContent(){
        return "Content";
    }
    
    private string GetEndingMarkup(){
        return "</span>";
    }
}

I am expecting when this gets displayed to have...

<span class="example">
Content
<span>Inner Content</span>
</span>

Instead, the content appears outside the span tag...

<span class="example"></span>
<!--!-->
Content
<!--!-->
<!--!-->
<span>Inner Content</span>

The content between the markup strings needs to be editable as the final version will include logic to embed other html and components

Any ideas how to get the intended behaviour?

Upvotes: 1

Views: 598

Answers (1)

Brian Parker
Brian Parker

Reputation: 14593

The render engine auto closes your element.

DynamicElement.cs

This component takes the element name and uses attribute splatting.

public class DynamicElement : ComponentBase
{
    [Parameter]
    public string ElementName { get; set; }

    [Parameter(CaptureUnmatchedValues = true)]
    public Dictionary<string, object> Attributes { get; set; }

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.OpenElement(sequence: 0, ElementName);
        builder.AddMultipleAttributes(sequence: 1, Attributes);
        builder.AddContent(sequence: 2, ChildContent);
        builder.CloseElement();
    }
}

Usage

<DynamicElement ElementName="span" class="example">
    @GetContent()
</DynamicElement>
@code {
    private string GetContent()
    {
        return "Content";
    }
}

Output

<!--!-->
<span class="example">Content</span>

Upvotes: 1

Related Questions