Blazor.DynamicJS is a library for writing JavaScript using C#
Write code in duck typing using dynamic.
You can also write code using types by assigning an interface. Just define an interface and Blazor.DynamicJS will use DispatchProxy to provide the implementation.
Blazor.DynamicJS from NuGet.
PM> Install-Package Blazor.DynamicJS
@using Blazor.DynamicJS
@inject IJSRuntime JS
@implements IAsyncDisposable
DynamicJSRuntime? _js;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
_js = await JS.CreateDymaicRuntimeAsync();
}
public ValueTask DisposeAsync()
=> _js?.DisposeAsync() ?? ValueTask.CompletedTask;
void DomSample()
{
dynamic window = _js.GetWindow();
dynamic button = window.document.createElement("button");
button.innerText = "new button";
dynamic div = window.document.getElementById("parent-div");
div.append(button);
//call back
button.addEventListener("click", (Action<dynamic>)(e => {
string detail = e.detail.toString();
window.console.log($"clicked {detail}");
}));
}
<script>
TestTargets =
{
Rectangle: class {
constructor(height, width) {
this.height = height;
this.width = width;
}
},
sum: function (...theArgs) {
let total = 0;
for (const arg of theArgs) {
total += arg;
}
return total;
},
data: 100,
list:[1, 2, 3, 4],
}
</script>
void GlobalSample()
{
dynamic window = _js.GetWindow();
dynamic targets = window.TestTargets;
//call function
int sum = targets.sum(1, 2, 3, 4);
window.console.log(sum);
//new class
dynamic rect = new JSSyntax(targets.Rectangle).New(10, 20);
window.console.log(rect.height);
window.console.log(rect.width);
//set data
targets.data = 100;
//get data
int data = targets.data;
window.console.log(data);
//array
for (int i = 0; i < (int)targets.list.length; i++)
{
window.console.log(targets.list[i]);
}
//add data
window.newData = new { num = 100, text = "text" };
window.console.log(window.newData.num);
window.console.log(window.newData.text);
}
export class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
export function sum(...theArgs) {
let total = 0;
for (const arg of theArgs) {
total += arg;
}
return total;
}
export let data = 100;
async Task ModuleSample()
{
//Please specify with absolute path
dynamic mod = await _js.ImportAsync("/module.js");
//call function
int sum = mod.sum(1, 2, 3, 4);
//new class
dynamic rect = new JSSyntax(mod.Rectangle).New(10, 20);
//get data
int data = mod.data;
}
<div @ref="_elementReferenceSample">sample element reference</div>
void ElementReferenceAndToJSSample()
{
dynamic jsElement = _js.ToJS(_elementReferenceSample);
jsElement.innerText = "test";
dynamic jsVariable = _js.ToJS(new { a = 0, b = 1 });
}
async Task AsyncSample()
{
dynamic targets = _js.GetWindow().TestTargets;
//sometimes methods will want to be called async.
//in that case, there is a simple way to write something like this.
int sum2 = await targets.sum(1, 2, 3, 4, new JSAsync<int>());
await targets.sum(1, 2, 3, 4, new JSAsync());
//You can also make properties and new async using JSSyntax.
//Methods can also be made async this way
//call function
int sum = await new JSSyntax(targets.sum).InvokeAsync<int>(1, 2, 3, 4);
//void or not use result
await new JSSyntax(targets.sum).InvokeAsync(1, 2, 3, 4);
//new class
dynamic rect = await new JSSyntax(targets.Rectangle).NewAsync(10, 20);
//set data
await new JSSyntax(targets.data).SetValueAsync(100);
//get data
int data = await new JSSyntax(targets.data).GetValueAsync<int>();
//array
int length = await new JSSyntax(targets.list.length).GetValueAsync<int>();
for (int i = 0; i < length; i++)
{
int val = await new JSSyntax(targets.list).GetIndexValueAsync<int>(i);
}
}
[JSCamelCase]
public interface IArray
{
int Length { get; }
int this[int index] { get; set; }
}
[JSCamelCase]
public interface IRectangle
{
int Height { get; set; }
int Width { get; set; }
}
[JSCamelCase]
public interface ITestTargets
{
[JSConstructor, JSIgnoreCase]
IRectangle Rectangle(int h, int w);
int Data { get; set; }
IArray List { get; set; }
int Sum(params int[] values);
//if you need async
Task<int> SumAsync(params int[] values);
}
async Task AssignInterfaceSample()
{
ITestTargets targets = new JSSyntax(_js.GetWindow().TestTargets).AssignInterface<ITestTargets>();
//call function
int sum = targets.Sum(1, 2, 3, 4);
int sum2 = await targets.SumAsync(1, 2, 3, 4);
//new class
IRectangle rect = targets.Rectangle(10, 20);
//set data
targets.Data = 100;
//get data
int data = targets.Data;
//array
for (int i = 0; i < (int)targets.List.Length; i++)
{
int val = targets.List[i];
}
//New, ToJS, ImportModule, GetWindoew
}