dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.2k stars 9.94k forks source link

DOM API Bindings and Blazor support #28820

Open marinasundstrom opened 3 years ago

marinasundstrom commented 3 years ago

This probably falls under runtime but I think it is relevant to the Web framework.

There is a project in the Mono repository for generating bindings to the DOM API through JavaScript interop. The plan/idea is to generate the C# code bindings from TypeScript. But it seems like the effort is on hold.

See: https://github.com/mono/mono/issues/10775

However: I see an opportunity in combining that effort with Blazor, enabling developers to use these classes directly from Razor. (Just for Blazor Web, of course)

Instead of an ElementReference you could cast a random HTML element into its corresponding class to perform stuff you otherwise would need manually write JavaScript (if there is not a third-party library for that)

We need this functionality in order to build powerful web apps with just C#.

I have not thought about the server-side scenario, but I guess that you could trigger JavaScript in the browser similar to today.

<canvas @ref="myCanvas" height="200" width="200" />

@code 
{
    Canvas myCanvas;
    Canvas2DContext context;

    protected async Task OnAfterRenderAsync(bool firstRender) 
    {
       if(!firstRender) 
       {
            if(context == null) 
            {
                context = await myCanvas.GetContextAsync("2d");
            }
            var image = new Img();
            image.Href = "/foo.png";
            await context.DrawImageAsync(image, 25, 25);
        }
    }
}
ghost commented 3 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

IvanJosipovic commented 3 years ago

@SteveSandersonMS, I'm not sure how this task was categorized as "affected-few". This issue literally affects every single Blazor user. Having these capabilities will avoid us having to use tones of JS wrapper NuGet libraries.

Other languages already have this in the works: https://rustwasm.github.io/wasm-bindgen/examples/dom.html https://github.com/golang/go/wiki/WebAssembly#interacting-with-the-dom

AlbertoPa commented 3 years ago

@SteveSandersonMS, I'm not sure how this task was categorized as "affected-few". This issue literally affects every single Blazor user. Having these capabilities will avoid us having to use tones of JS wrapper NuGet libraries.

I agree with this. I think it affects more users that we may think, but some just accepted the idea that they should rely on third-party wrappers or write their own JS. Just my 2 cents.

SteveSandersonMS commented 3 years ago

The reasoning is just that directly mutating the DOM is not a primary part of Blazor's UI rendering model. The vast majority of scenarios are handled more efficiently using .razor syntax which ties in with the diff-based rendering system and works well in all hosting models (WebAssembly, Server, WebView).

I totally understand there are cases where you need to step outside this model, which is what JS interop provides for. Perhaps it would be interesting to use this to start a community project that provides access to the full range of JS APIs via .NET wrappers. In the long run, depending on community feedback, it's something that the ASP.NET team might also look into doing, but it's not part of the roadmap for .NET 6.

ghost commented 2 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

RealGoodAnthony commented 2 years ago

@marinasundstrom I have actually been working on exactly this here! https://github.com/RealGoodAppsLLC/BlazorJavascript

Would love some help :) I have been making some really good progress. What I basically do is take the TypeScript definition files for the DOM and export some JSON files that define their structure. Then I pipe that into a CodeGenerator which generates C# classes for all the things. I need to improve the documentation, but I have been streaming the development effort over on Twitch (my username is Anthonutty).

Here is a little example of it in action: https://github.com/RealGoodAppsLLC/BlazorJavascript/blob/main/Interop/test/BlazorSample/Views/IndexView.razor#L17

RealGoodAnthony commented 2 years ago

@marinasundstrom I have released the first iteration of RealGoodApps.BlazorJavascript.Interop, which gives you access to the entire window object in Blazor WASM. I have a roadmap of issues to address soon, but these are things that are top of mind for me: 1) Non-WASM support 2) Smaller binary size 3) Syntax sugar for coercing Promise<T> to and from Task<T>.

Nuget package: https://www.nuget.org/packages/RealGoodApps.BlazorJavascript.Interop/ Getting started: https://github.com/RealGoodAppsLLC/BlazorJavascript#getting-started