My Blazor server side app has several js / css libraries included in the _Layout.cshtml file. However, in one of my components I want to leverage an additional set of js / css libraries to add functionality for that specific component-- I don't want these libraries to get loaded globally.
Is there a way to do this that is native to Blazor? I've seen many posts that use a third-party library or some sort of hack to accomplish this (for example https://github.com/mishelshaji/DynamicJavaScriptInBlazor), but it seems like something that ought to be supported natively.
Using the lazy loading feature of IJSRuntime you can dynamically load JavaScript with your component.
In this component I lazy load a script file within a Razor Class Library.
Relevant sections from a code behind approach component:
public partial class Dialog : ComponentBase, IAsyncDisposable
{
private readonly Lazy<Task<IJSObjectReference>> moduleTask;
private DotNetObjectReference<Dialog> dotNetObjectReference;
...
public Dialog()
{
moduleTask = new(() => jsRuntime!.InvokeAsync<IJSObjectReference>(
identifier: "import",
args: "./_content/BlazorDialogs/dialogJsInterop.js")
.AsTask());
dotNetObjectReference = DotNetObjectReference.Create(this);
}
[Inject]
private IJSRuntime jsRuntime { get; set; }
...
public async ValueTask ShowDialogAsync()
{
var module = await moduleTask.Value;
await module.InvokeVoidAsync(identifier: "showDialog", dialogElement, dotNetObjectReference);
...
}
public async ValueTask CloseDialogAsync()
{
var module = await moduleTask.Value;
await module.InvokeVoidAsync(identifier: "closeDialog", dialogElement);
...
}
[JSInvokable]
public void OnDialogClosed()
{
...
}
public async ValueTask DisposeAsync()
{
if (moduleTask.IsValueCreated)
{
var module = await moduleTask.Value;
await module.DisposeAsync();
}
}
}
Note: OnDialogClosed is called from the JavaScript.
Repo
Related
To compile C# into WebAssemly and interop with JS it's required to use Blazor WebAssembly ASP.NET framework, which is designed for SPA and contains lot of overhead in case you just want to use a C# library from JS.
What is the minimum setup to just compile a DLL to WebAssembly and use it from JavaScript?
Create a new empty C# project with the following configuration (via .csproj):
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>10</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.0" PrivateAssets="all" />
</ItemGroup>
</Project>
Initialize Blazor JS runtime and specify the bindings:
namespace WasmTest;
public class Program
{
private static IJSRuntime js;
private static async Task Main (string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
var host = builder.Build();
js = host.Services.GetRequiredService<IJSRuntime>();
await host.RunAsync();
}
[JSInvokable]
public static async Task<string> BuildMessage (string name)
{
var time = await GetTimeViaJS();
return $"Hello {name}! Current time is {time}.";
}
public static async Task<DateTime> GetTimeViaJS ()
{
return await js.InvokeAsync<DateTime>("getTime");
}
}
Publish with dotnet publish and use the C# library from JS:
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script>
window.getTime = () => {
return new Date().toJSON();
};
window.onload = async function () {
await Blazor.start();
const msg = await DotNet.invokeMethodAsync("WasmTest", "BuildMessage", "John");
console.log(msg);
};
</script>
Alternatively, here is a solution, that allows compiling C# project into single-file UMD library, which can be consumed in any JavaScript environment: browsers, node, and custom restricted environments, such as VS Code's web extensions: https://github.com/Elringus/DotNetJS
Actually, I have existing SDKs and I wanted to use that SDK in the react native app.
For android
I tried adding the jar file into the libs folder of /android/app/
Added dependencies into file /android/app/build.gradle
implementation fileTree(include: ['*.jar'], dir: 'libs')
But I did not get how can I use these jar files in my js file. How can I create the object and call the methods?
The main concern is how can I use the external java libraries in my react native app?
You should use native modules them are bridge between JS and native
https://reactnative.dev/docs/native-modules-android
Example
public class DummyModule extends ReactContextBaseJavaModule {
MyDummyClass dummy // this context
public DummyModule(final ReactApplicationContext reactContext){
super(reactContext);
}
#Override
// getName is required to define the name of the module represented in
// JavaScript
public String getName() {
return "DummyModule";
}
#ReactMethod
public void startMyClass() {
this.dummy = new MyDummyClass();
}
#ReactMethod
public void fooActionClass() {
if(this.dummy != null){
this.dummy.fooAction();
}
}
}
In your javascript code
import { NativeModules } from 'react-native';
const dummyModule = NativeModules.DummyModule;
dummyModule.startMyClass();
// Make sure that u call the action when the class is instanciated.
dummyModule.fooActionClass();
Usefull question as well Sending hashmao from java to react native
I am trying to write a VS Code extension for Aurelia that will provide intellisense in the HTML file for properties and methods that are in its paired viewmodel typescript class.
I can get to the typescript file but I need a tool to analyze to extract the properties of the viewmodel class. Here is an example of such a class:
import { HttpClient } from 'aurelia-fetch-client';
import { observable, inject } from 'aurelia-framework';
#inject(HttpClient)
export class People {
public people: Person[];
#observable selectedPerson: Person;
private httpClient: HttpClient
public updateMessage: string;
constructor(http: HttpClient) {
this.httpClient = http;
this.httpClient.fetch('http://localhost:5555/api/Persons?$top=10')
.then(result => result.json() as Promise<ODataPerson>)
.then(data => {
this.people = data.value;
});
}
setSelected(selected: Person) {
this.selectedPerson = selected;
}
activate() {
...
}
}
So I'd like to extract from this an array of the properties, i.e. people, selectedPerson, and updateMessage, and also if possible any public methods, i.e. setSelected.
The best way to do this would be to consume the class with a Require, and then use javascript reflection e.g.
var Reflector = function(obj) {
this.getProperties = function() {
var properties = [];
for (var prop in obj) {
if (typeof obj[prop] != 'function') {
properties.push(prop);
}
}
return properties;
};
But to do this I'd have to compile the ts file down to Javascript and then I still couldn't consume it because to import and inject dependencies like HttpClient it needs to be running as part of the Aurelia application, whereas I am running from the context of a VS Code extension.
So I was looking at tools that might be able to analyse the code statically without consuming it, such as TSLint, but I can't see any facility to extract class properties and methods.
Does anyone know of any tools out there that could do what I'm trying to achieve?
You should use the compiler itself to achieve this. The compiler provides an API for intel sense that is used in all IDEs that support typescript. Link to the API. The language service should be able to analize the class and provide the information. I would look into weather you can't acces the Language service that is already running in VS Code, but I don't have info on that.
I am tasked to compile the gwt project(which doesnot include HTML CSS) into JS files and add the same to an external JS/HTML file( which is in different project).
here is the java code which has to be compiled:
1. Client class:
package com.dell.supportassist.gwt.collectionReport.client;
import org.timepedia.exporter.client.Export;
import org.timepedia.exporter.client.Exportable;
#Export("HelloWorld")
public class HelloWorld implements Exportable {
public String sayHello(){
return "Hello";
}
}
EntryPoint Class:
package com.dell.supportassist.gwt.collectionReport.client;
import org.timepedia.exporter.client.Export;
import org.timepedia.exporter.client.Exportable;
#Export("HelloWorld")
public class HelloWorld implements Exportable {
public String sayHello(){
return "Hello";
}
}
My issue is, once the above gwt project/classes are complied, i want to access 'sayHello()' method in ma external javascript like this:
var person = hello.sayHello();
system.log(person);
But this is throwing a run time error saying 'hello' is not defined.
P.S I am trying to use the GWT compiled JS in an external HTML, JS Present in Durandaljs Framework.
Haven't done this kind of stuff for quite some time but you could achieve this using JSNI, which allows you to write native JS in GWT. From JSNI you can reference your GWT methods. That way you could define a function (on window, most typically) which would then become available to regular JS. From this JSNI-method you can reference your GWT/Java code.
Code example:
public class MyModule implements EntryPoint {
static {
export();
}
/**
* Makes our setData method accessible from plain JS
*/
private static native void export() /*-{
$wnd.setData = #my.package.MyModule::setData(Lcom/google/gwt/core/client/JavaScriptObject;);
}-*/;
private static void setData(JavaScriptObject javaScriptObject) {
// this method is now reachable as window.setData
}
}
I have a class library written in Java and want to convert it to Javascript. All methods are pretty simple and mostly have to do with manipulating collections. I have this one class, GameControl, which I could instantiate and I want its methods exposed to other Javascript code on the page.
I thought to use GWT. I have a running project in GWT which compiles, but I can't figure out how to expose my instance (+functionality) of the GameControl class.
I thought using JSNI to expose my object should work, but it didn't. This is the short version of how it look like right now:
GameEntryPoint.java
import com.google.gwt.core.client.EntryPoint;
public class GameEntryPoint implements EntryPoint {
private GameControl _gameControl;
#Override
public void onModuleLoad() {
_gameControl = new GameControl();
expose();
}
public native void expose()/*-{
$wnd.game = this.#game.client.GameEntryPoint::_gameControl;
}-*/;
}
GameControl.java
package game.client;
public class GameControl {
public boolean isEmpty(int id){
// does stuff...
return true;
}
}
So, GWT indeed compiles the code, and I see that there is a GameControl_0 object being built and set into $wnd.game, but no isEmpty() method to be found.
My expected end result is to have a window.game as an instance of GameControl with all public methods GameControl exposes.
How can I do this?
Edit
As per #jusio's reply, using JSNI to expose window properties explicitly worked, but it was too verbose. I'm trying the gwt-exporter solution. Now I have
GameEntryPoint.java
package game.client;
import org.timepedia.exporter.client.ExporterUtil;
import com.google.gwt.core.client.EntryPoint;
public class GameEntryPoint implements EntryPoint {
#Override
public void onModuleLoad() {
ExporterUtil.exportAll();
}
}
RoadServer.java
package game.client;
import org.timepedia.exporter.client.Export;
import org.timepedia.exporter.client.ExportPackage;
import org.timepedia.exporter.client.Exportable;
#ExportPackage("game")
#Export("RoadServer")
public class RoadServer implements Exportable {
int _index;
int _id;
public RoadServer(int index,int id){
this._id=id;
this._index=index;
}
}
but still none of the code is exported (specifically not RoadServer).
You have exposed only instance of the GameControl. If you want to expose other methods, you'll have to expose them as well.
For example:
public native void expose()/*-{
var control = this.#game.client.GameEntryPoint::_gameControl;
var gameInstance = {
gameControl: control,
isEmpty:function(param){
control.#game.client.GameEntryPoint::isEmpty(*)(param);
}
}
$wnd.game = gameInstance;
}-*/;
Also there is a framework called gwt-exporter, it might make things easier for you
This may help.
http://code.google.com/p/gwtchismes/wiki/Tutorial_ExportingGwtLibrariesToJavascript_en