Skip to content

(Suggestion) Blazor: RenderFragment target String #39506

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
LukeTOBrien opened this issue Jan 13, 2022 · 3 comments
Closed

(Suggestion) Blazor: RenderFragment target String #39506

LukeTOBrien opened this issue Jan 13, 2022 · 3 comments
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-rendering Features dealing with how blazor renders components ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. question Status: Resolved

Comments

@LukeTOBrien
Copy link

Hello,

I would like to return a RendeFragment as a string, I understand this is not currently possible but I would like to suggest the idea for future consideration.
This issue is the same as #22266 and #9493

Use case

In my case I am creating a wrapper component around a WebComponent I have, in my WebComponent I have a itemTemplate function that returns a Promise<string>:

itemTemplate: (obj: any) => Promise<string>;

Inside the OnAfterRenderAsync method, I then call the JavaScript function to set the itemTemplate:

setItemTemplate = (id: string, dotNet: DotNet.DotNetObject) => {
        let el = document.getElementById(id);
        if (el) {
            el.itemTemplate = (obj) => {
                return dotNet.invokeMethodAsync<string>('OnItemTemplate', obj);
            }
        }
    }

Finally in the Blazor component I return the RenderFragment as a string: ( I have found a hacky workaround)

[JSInvokable]
        public async Task<string> OnItemTemplate(T obj)
        {
            var fragment = ItemTemplate(obj);
            var builder = new RenderTreeBuilder();
            fragment(builder);
            var els = builder.GetFrames().Array.Where(x => !string.IsNullOrWhiteSpace(x.MarkupContent));
            var html = string.Join("", els.Select(x => x.FrameType == RenderTreeFrameType.Element ? $"<{x.MarkupContent}>" : x.MarkupContent));
            return html;
        }

Possible solution

The fragment renders to a RenderTreeBuilder , would it be be possible to abstract the TreeBuilder into an interface?

[JSInvokable]
        public async Task<string> OnItemTemplate(T obj)
        {
            var fragment = ItemTemplate(obj);
            var target = new StringRenderer();
            fragment(target);
            return target.GetString();
        }

What are your thoughts on this?

@TanayParikh TanayParikh added area-blazor Includes: Blazor, Razor Components feature-rendering Features dealing with how blazor renders components enhancement This issue represents an ask for new feature or an enhancement to an existing one labels Jan 13, 2022
@TanayParikh
Copy link
Contributor

Note; may be related to #17200.

@TanayParikh TanayParikh added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Jan 13, 2022
@javiercn
Copy link
Member

@LukeTOBrien thanks for contacting us.

This is not something we support.

There are technical reasons for it, like the fact that we don't know the instantiation of the type parameter T when you invoke it through JavaScript and even if we knew, we can't allow unbounded generic instantiations as that would lead to a type explosion.

One path forward that might work is to use a JS root component to represent the template for the item, in that case, inside your content you can render a JS root component and that should allow you to pass in an argument (you would need to specify a concrete type)

@javiercn javiercn added ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. question labels Jan 17, 2022
@ghost ghost added the Status: Resolved label Jan 17, 2022
@ghost
Copy link

ghost commented Jan 18, 2022

This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes.

See our Issue Management Policies for more information.

@ghost ghost closed this as completed Jan 18, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Feb 17, 2022
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-rendering Features dealing with how blazor renders components ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. question Status: Resolved
Projects
None yet
Development

No branches or pull requests

3 participants