Giter Site home page Giter Site logo

blazorbindgen's Introduction

BlazorBindGen

NuGet Package NuGet Badge License: MIT

A binding generator for JS, Call any JS function or property in Blazor Wasm and Server (Including MAUI hybrid) without writing JS wrappers.

Why Use BlazorBindGen

  • very tiny Overhead ~13kb
  • No need to write JS wrappers
  • Support for Callbacks
  • Write JS code in C#
  • WASM and Server Supported
  • automatic memory management

Installation

Use Nuget Package Manager or .Net CLI

dotnet add package BlazorBindGen

Initialize BindGen

  1. on top of razor page add Import statements
@inject IJSRuntime runtime
@using BlazorBindGen
@using static BlazorBindGen.BindGen
@using JSCallBack=System.Action<BlazorBindGen.JObjPtr[]>; //optional Typedef 
  1. Intitialize the BindGen
    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        await InitAsync(runtime);
    }
    //on Server 
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
	if (!firstRender)
		return;
	await InitAsync(runtime);	
    }

Binding Samples

-> Js code is for explaination purpose only , you do not need to write js code anywhere.
-> On Server use Async Version of functions (non async functions will throw `PlatformNotSupportedException`)
Import JS libaries when ever you want in C#
// js equivalent
await import("https://unpkg.com/ml5@latest/dist/ml5.min.js");
//c# side
await ImportAsync("https://unpkg.com/ml5@latest/dist/ml5.min.js");

// js equivalent, importing modules 
let ml5=await import("https://unpkg.com/ml5@latest/dist/ml5.min.js");
//c# side
var ml5Ptr=await ImportRefAsync("https://unpkg.com/ml5@latest/dist/ml5.min.js");
Constructor Calls
//js side
var audio=new Audio(param);

//c# side code 
var_audio=Window.Construct("Audio",param); /* js reference to Audio Player */ 
Fuction Calls
//js equivalent 
alert("Hello");

//code to call alert in C#
Window.CallVoid("alert","hello");
Share JS object References
//js equivalent 
var video = document.querySelector("#videoElement");
//here document is property of window , and dcument has function querySelector


//c# code 
var video = Window["document"].CallRef("querySelector", "#videoElement");
//["documemnt"] will return reference to Property document of window , another way to write it is 
JObjPtr video = Window.PropRef("document").CallRef("querySelector", "#videoElement");
//CallRef function calls JS function and Returns a reference to it, instead of whole object 
Get Set Properties
// equivalent js code 
var ctx = c.getContext("2d");
var grd = ctx.createRadialGradient(75, 50, 5, 90, 60, 100);
ctx.fillStyle = grd;
		
//c# side 
var ctx=canvas.CallRef("getContext","2d");
var grad = ctx.CallRef("createLinearGradient", 0,0,400,0);
ctx.SetPropRef("fillStyle",grad); 
//assign a reference to grad(a JobjPtr reference) to property fillStyle of canvas context
Mapping JS property to C#
//js
var audio=new Audio();
audio.currentTime=6; //set
console.log(audio.currentTime); //get

//c# equivalent
JObjPtr _audio=Window.Construct("Audio"); /* js reference to Audio Player */ 
public double CurrentTime
{
    get => _audio.PropVal<double>("currentTime");
    set => _audio.SetPropVal("currentTime", value);
}
Map Js Callback to C# event
//js equivalent
var audio=new Audio();
audio.onloadeddata=()=>{ console.log("loaded"))};

//cs equivalent
{
   var _audio=Window.Construct("Audio"); /* js reference to Audio Player */ 
   _audio.SetPropCallBack("onloadedmetadata", (_) => OnLoadedMetaData?.Invoke(this));
}
public delegate void LoadedMetaDataHandler(object sender);
public event LoadedMetaDataHandler OnLoadedMetaData;

Be sure to check out sampleApp for more examples

Example (using ML5 in C# only)

@page "/ml5"

@using BlazorBindGen
@using static BlazorBindGen.BindGen
@using JSCallBack=System.Action<BlazorBindGen.JObjPtr[]>; //optional only needed to simplify callback type name

@inject IJSRuntime runtime

@if (isLoaded)
{
    <input type="text" class="bg-dark text-white border-light" @bind="predictText" placeholder="write review here " style="font-size:18px"/>
    <button class="btn btn-primary" id="mbtn" @onclick="Predict">Predict</button><br /><br />
    if(score>0)
    {
        <div class="alert alert-primary">
            <p>Review: @GetEmoji() <br />Score: @score</p>
        </div>
    }
}
else
{
    <div class="alert alert-warning">
        Fetching Movie Review Dataset (~16 MB)
    </div>
}
@code
{
    JWindow win;
    public JObjPtr sentiment;
    string predictText;
    bool isLoaded = false;
    double score;

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        await Init(runtime);
        win = Window;
        await ML5Init();
    }

    async Task ML5Init()
    {
        await Import("https://unpkg.com/ml5@latest/dist/ml5.min.js");
        Console.Clear();
        var ml5 = win["ml5"];
        sentiment = ml5.CallRef("sentiment", "movieReviews", (JSCallBack)OnModelLoaded);
    }

    void Predict()
    {
        var v = sentiment.Call<Score>("predict", predictText);
        score=v.score;
        StateHasChanged();
    }

    void OnModelLoaded(params JObjPtr[] args)
    {
        isLoaded = true;
        StateHasChanged();
    }

    string GetEmoji()
    {
        if (score > 0.7)
            return "๐Ÿ˜€";
        else if (score > 0.4)
            return "๐Ÿ˜";
        else
            return "๐Ÿ˜ฅ";

    }

    record Score(double score);

}

Experimentation Auto Bind Generator for WASM

Above example binding could also be generated with Source Generator for WASM .

using BlazorBindGen.Attributes;

namespace SampleApp.JSBinding
{
    [JSWindow] // represents JS Window class
    public static partial class DomWindow  
    {
        [JSProperty] 
        private static ML5 ml5; // refers to window.ml5 prop js side

    }
    [JSObject("https://unpkg.com/ml5@latest/dist/ml5.min.js")]
    public partial class ML5
    {
        [JSFunction("sentiment")]
        public partial Sentiment Sentiment(string modelName,OnModelLoadHandler onModelLoad);

        [JSCallback]
        public delegate void OnModelLoadHandler();

        [JSConstruct("p5")]
        public partial Sentiment Construct();
    }
    [JSObject]
    public partial class Sentiment
    {
        [JSFunction("predict")]
        public partial Score Predict(string text);
    }
    public record Score(double score);


}

see usage here

Warning

  1. BlazorBindGen Api is subject to change, API is not stable.
  2. Note: Blazor Server requires use of Async functions otherwise UI thread will be blocked by it or alternatively you can call BindGen functions on different thread
    #issue.

blazorbindgen's People

Contributors

sps014 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.