Blazor.JS.Component 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Blazor.JS.Component --version 1.0.0                
NuGet\Install-Package Blazor.JS.Component -Version 1.0.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Blazor.JS.Component" Version="1.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Blazor.JS.Component --version 1.0.0                
#r "nuget: Blazor.JS.Component, 1.0.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Blazor.JS.Component as a Cake Addin
#addin nuget:?package=Blazor.JS.Component&version=1.0.0

// Install Blazor.JS.Component as a Cake Tool
#tool nuget:?package=Blazor.JS.Component&version=1.0.0                

Blazor.JS.Component

An expansion to Blazor that adds the ability to painlessly attach a JS module counterpart to Razor components.

This library relies on Blazor's JavaScript and C# interoperability capabilities. I recommend familiarizing yourself with the JS interop API before using Blazor JS Components.

Purpose

The library's main purpose is to provide a more developer-friendly way to interop between C# and JS on a per-component basis, making for a cleaner project and more readable code.

In some projecs you'd want to use JS libraries alongside your C# code, as most of them have no C# bindings. Blazor's current implementation of JS interop requires you to add a static JS file and load it by invoking "import" via JSRuntime.

This library does it automatically for you. All you have to do is add a .razor.js file to the same folder as your .razor component, and it will find the path, load the module, and call the "initializer" function with all the params you need for a (somewhat) clean and painless interop experience.

Getting Started

[TBA - NuGet Package]

  1. In your Razor component, add @inherits JSComponent at the top.
  2. At the same folder as your componnet, add a JavaScript file with the same name as the component and a .razor.js extension. For example: Counter.razor.js. If you're using Visual Studio (not Code) you'll see it nested under your Razor component.
  3. In your JavaScript file, add a function with the following signature: export function ComponentName(rootElement, dotNetObjectRef).
  4. In your Razor Component's HTML, wrap the content in an element and add @ref="rootElement" to it. The root element is necessary for selecting HTML elements relative to your component in the JS module.
  5. Add any JS code you'd like to apply to your component to the function's body.

Main Usage

Handling a JavaScript event with a C# method

JavaScript:

export function Counter(rootElement, dotNetObjRef) {
    root = rootElement;
    const button = rootElement.querySelector("#my-button");
    const hammer = new Hammer(button);
    hammer.on("pan", (ev) => {
        dotNetObjRef.invokeMethod("HandlePan", { deltaX: ev.deltaX, deltaY: ev.deltaY });
    });
}

C#:

public record DeltaParams(int deltaX, int deltaY);

[JSInvokable]
public void HandlePan(DeltaParams param)
{
    CurrentCount += param.deltaY;
    StateHasChanged();
}

In this example, I use the hammer.js library to add a pan event to my button, and handle the event in the C# counterpart of the component.

  • Note that I extracted only the specific properties I needed, and added a corresponding record to C# to handle the values. This is necessary due to JS event objects having circular references and not being JSON.stringify-able. I recomment always creating a custom type, may it be a class or record, for handling event args.

  • Also note how I used the rootElement along with querySelector to select a child relatively to the root. This way you can access the specific instance's children, rather than making global selectors.

Getting a C# property value from JavaScript

Using the GetProperty method of JSComponent, you can get any property by name:

const currentCount = dotNetObjRef.invokeMethod("GetProperty", "CurrentCount");

<i>DISCLAIMER: the GetProperty method uses reflection and it's not guaranteed to run smoothly when called in loops. It is recommended to implement a custom getter method for the purpose of multiple consecutive calls.</i>

Unfortunately due to type casting issues, if you want to set the property from JS, you'd have to implement a custom setter method:

[JSInvokable]
public void SetCurrentCount(int newCount) 
{
    CurrentCount = newCount;
    StateHasChanged();
}

And invoke it from the JS module:

dotNetObjRef.invokeMethod("SetCurrentCount", 3);
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.1.3 326 3/16/2023
1.0.1.2 312 12/3/2022
1.0.1.1 307 12/3/2022
1.0.1 325 12/3/2022
1.0.0 316 12/3/2022

Initial release