'Blazor RenderFragment to String
I'm developing a code block component using .Net 6 Blazor wasm
. I need to display the RenderFragment
as string
and also render the component in my html.
Here is my code block component,
<pre class="language-html">
<code class="language-html">
@("Some way to get non rendered html from @ChildContent")
</code>
</pre>
@ChildContent
@code
{
[Parameter]
public RenderFragment ChildContent { get; set; }
}
I'm using the above component as,
<CodeBlock>
<Chat></Chat>
</CodeBlock>
Expected Output:
<Chat></Chat>
<!-- This is the input I passed inside as RenderFragment and I need the exact Render Fragement Code;
not the Rendered Html code of the RenderFragment -->
Component gets rendered as expected. But unable to get non rendered html of my RenderFragment
One option is to pass the RenderFragment
content as string parameter to CodeBlock
component. But this results in duplicate and non readable HTML
. Also this becomes difficult to maintain when the ChildContent
has multiple lines of code.
<CodeBlock Html="@("<Chat></Chat>")">
<Chat></Chat>
</CodeBlock>
Any hints/suggestions on how to achieve this?
Solution 1:[1]
This is kind of a tough question. From what I understand you want to be able to render the ChildContent
of your component but also be able to view the ChildContent
data as plaintext razor code, or HTML if that's what's in your ChildContent
, right?
So an option would be to surround your @ChildContent
renderer tag with a <div>
and assign that div a unique id when the parent component is initialized. Then you create another variable, let's call it private string RawContent { get; set; }
. Then write a javascript function that takes an id value and gets the element by id from the DOM and returns the element's innerHTML
.
I created a test project to try it and it works. Here are the snippets that are relevant.
In your Component.razor
file:
@inject IJSRuntime JS
<pre class="language-html">
<code class="language-html">
@RawContent
</code>
</pre>
<div id="@ElementId">
@ChildContent
</div>
@code
{
[Parameter]
public RenderFragment ChildContent { get; set; }
private ElementReference DivItem { get; set; }
private string RawContent { get; set; }
private Guid ElementId { get; set; } = Guid.NewGuid();
protected async override Task OnInitializedAsync()
{
base.OnInitializedAsync();
RawContent = await JS.InvokeAsync<string>("GetElementHtmlText", ElementId.ToString());
}
}
Then in your index.html
file add this in side of a <script>
tag, or to one of your javascript files:
async function GetElementHtmlText(elementID) {
await setTimeout(() => { }, 1);
console.log(elementID);
var element = document.getElementById(elementID);
console.log(element);
var result = element.innerHTML;
console.log(result);
return result;
}
Then anywhere you wish to use this component you will render the HTML markup and have the Raw Text available as well. However this function will return all of the html markup raw text, meaning that you get the razor tags and the empty comment elements that Blazor inserts as well (ie. <!--!-->
). But as long as you know that you can work around them.
I didn't do this but you could modify this to call the JSInterop function inside the RawContent
's getter instead of just when the component initializes.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | JG222 |