Aller au contenu principal

Interopérabilité JavaScript

L'interopérabilité JavaScript permet à une page ou un composant Blazor Lagoon d'appeler du code JavaScript, ou de recevoir un rappel depuis JavaScript.

Choisir l'approche​

BesoinApproche recommandée
Appel ponctuel : focus, scroll, presse-papiers, librairie JavaScript simpleIJSRuntime directement.
Objet JavaScript persistant avec cycle de vie, événements DOM à nettoyer, état côté JavaScriptJSInteropBase, uniquement si ce besoin est explicite.
Règle par défaut

Utilisez IJSRuntime directement. JSInteropBase est réservé aux composants avancés qui ont réellement besoin d'un objet JavaScript persistant et disposable.

Approche simple avec IJSRuntime​

Fichier JavaScript​

Placez le script dans les ressources Web de l'application, puis référencez-le comme les autres scripts applicatifs du projet.

wwwroot/js/sample-chart.js
window.SampleChart = window.SampleChart || {};

window.SampleChart.initialize = function (element, title) {
const paragraph = document.createElement('p');
paragraph.textContent = title;
element.appendChild(paragraph);
};

window.SampleChart.clear = function (element) {
element.replaceChildren();
};

Markup du composant​

Le fichier .razor contient uniquement le markup. Le code C# reste dans le fichier .razor.cs.

SampleChart.razor
@inherits LgComponentBase

<div @ref="_container"></div>

<LgButton Text="#ClearChart" OnClick="ClearAsync" />

Code-behind C#​

Injectez IJSRuntime, puis appelez les fonctions JavaScript depuis le cycle de vie ou depuis les handlers UI.

SampleChart.razor.cs
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;

namespace Demo.Client.Components;

public partial class SampleChart
{
private ElementReference _container;

[Inject]
private IJSRuntime JSRuntime { get; set; }

[Parameter]
public string Title { get; set; }

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// Initialise le widget JavaScript quand l'élément DOM existe.
await JSRuntime.InvokeVoidAsync("SampleChart.initialize", _container, Title);
}
}

private async Task ClearAsync(ActionEventArgs args)
{
try
{
// Délègue le nettoyage DOM à la fonction JavaScript.
await JSRuntime.InvokeVoidAsync("SampleChart.clear", _container);
}
catch (Exception ex)
{
ShowException(ex);
}
}
}

Callback JavaScript vers C#​

Utilisez DotNetObjectReference et une méthode [JSInvokable] lorsque le code JavaScript doit notifier le composant Blazor.

wwwroot/js/sample-callback.js
window.SampleCallback = window.SampleCallback || {};

window.SampleCallback.register = function (element, dotNetReference) {
element.addEventListener('click', function () {
// Notifie le composant Blazor après un événement DOM.
dotNetReference.invokeMethodAsync('OnJavaScriptClickAsync');
});
};
ClickablePanel.razor
@inherits LgComponentBase

<div @ref="_panel">
@ChildContent
</div>
ClickablePanel.razor.cs
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace Demo.Client.Components;

public partial class ClickablePanel : IDisposable
{
private ElementReference _panel;
private DotNetObjectReference<ClickablePanel> _dotNetReference;

[Inject]
private IJSRuntime JSRuntime { get; set; }

[Parameter]
public RenderFragment ChildContent { get; set; }

protected override void OnInitialized()
{
_dotNetReference = DotNetObjectReference.Create(this);
}

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// Transmet une référence .NET au script JavaScript.
await JSRuntime.InvokeVoidAsync("SampleCallback.register", _panel, _dotNetReference);
}
}

[JSInvokable]
public Task OnJavaScriptClickAsync()
{
ShowInformation("#PanelClicked");
return Task.CompletedTask;
}

public void Dispose()
{
_dotNetReference?.Dispose();
}
}

Approche avancée avec JSInteropBase​

JSInteropBase encapsule la création, le chargement, le rechargement et la libération d'un objet JavaScript. Le framework l'utilise pour des composants complexes comme les modales, les split containers ou l'éditeur HTML.

Règles d'utilisation​

  • Créer une classe C# interne qui hérite de JSInteropBase.
  • Passer le nom de la classe JavaScript au constructeur de base.
  • Charger l'objet avec LoadAsync() ou ToggleLoadAsync(true) lorsque l'élément DOM est disponible.
  • Libérer les ressources avec Dispose() ou DisposeAsync().
  • Côté JavaScript, étendre Lagoon.LgControl, utiliser addEvent() / addEvents() pour les événements et appeler super.dispose().
AdvancedWidget_JSInterop.cs
namespace Demo.Client.Components;

public partial class AdvancedWidget
{
private class JSInterop : JSInteropBase
{
public JSInterop(AdvancedWidget component, Func<JSConstructorArgs> getJSConstructorArgs)
: base(component, "AdvancedWidget", getJSConstructorArgs)
{ }

internal void Refresh(string value)
{
// Appelle une méthode exposée par l'objet JavaScript persistant.
JSObject?.InvokeVoid("refresh", value);
}
}
}
wwwroot/js/advanced-widget.js
Lagoon.AdvancedWidget = class extends Lagoon.LgControl {
#element;

constructor(dotNetReference, element) {
super(dotNetReference);
this.#element = element;
this.addEvent(this.#element, 'click', this.#onClick);
}

#onClick() {
// Remonte l'événement au composant Blazor.
this.invokeDotNetMethodAsync('OnWidgetClickAsync');
}

refresh(value) {
this.#element.dataset.value = value;
}

dispose() {
this.#element = null;
super.dispose();
}
}
À éviter

N'utilisez pas JSInteropBase pour un simple appel JavaScript. Dans ce cas, IJSRuntime est plus lisible et suffisant.