Skip to content

Commit

Permalink
Merge pull request #436 from LayTec-AG/feature/selected-event
Browse files Browse the repository at this point in the history
Add selected event
  • Loading branch information
sean-mcl authored Jun 17, 2024
2 parents f3fc751 + 9dc1354 commit d604c58
Show file tree
Hide file tree
Showing 12 changed files with 248 additions and 9 deletions.
82 changes: 82 additions & 0 deletions Plotly.Blazor.Examples/Components/Selected.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
@using Plotly.Blazor.Interop
@using Plotly.Blazor.LayoutLib
@using Plotly.Blazor.Traces.ScatterLib

<PlotlyChart style="height: 60vh; min-height: 350px"
@bind-Config="config" @bind-Layout="layout" @bind-Data="data" @ref="chart"
SelectedAction="SelectedAction" AfterRender="SubscribeEvents"/>

@if (SelectedInfos != null && SelectedInfos.Any())
{
@foreach (var selected in SelectedInfos)
{
<MudText>(Trace: @(selected.TraceIndex), X: @(selected.X), Y: @(selected.Y))</MudText>
}
}

@code
{
[CascadingParameter]
private MudTheme Theme { get; set; }

private PlotlyChart chart;
private Config config;
private Layout layout;
private IList<ITrace> data;
private IEnumerable<EventDataPoint> SelectedInfos { get; set; }

/// <inheritdoc />
protected override void OnInitialized()
{
config = new Config
{
Responsive = true
};

layout = new Layout
{
Title = new Title
{
Text = GetType().Name
},
PaperBgColor = Theme.PaletteDark.Surface.ToString(),
PlotBgColor = Theme.PaletteDark.Surface.ToString(),
Font = new Font
{
Color = Theme.PaletteDark.TextPrimary.ToString()
},
HoverMode = HoverModeEnum.XUnified
};

data = new List<ITrace>
{
new Scatter
{
Name = "ScatterTrace",
Mode = ModeFlag.Markers,
X = Enumerable.Range(0, 30).Cast<object>().ToList(),
Y = Helper.GenerateData(0, 30).Y
},
new Scatter
{
Name = "ScatterTrace 2",
Mode = ModeFlag.Markers,
X = Enumerable.Range(0, 30).Cast<object>().ToList(),
Y = Helper.GenerateData(0, 30).Y
}
};

base.OnInitialized();
}

public void SelectedAction(IEnumerable<EventDataPoint> eventData)
{
SelectedInfos = eventData;
StateHasChanged();
}

public async void SubscribeEvents()
{
await chart.SubscribeSelectedEvent();
}
}
5 changes: 5 additions & 0 deletions Plotly.Blazor.Examples/Pages/SelectedPage.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@page "/selected"

<Example Title="Scatter Chart with Selected-Event" Url="Plotly.Blazor.Examples/Components/Selected.razor">
<Selected />
</Example>
9 changes: 8 additions & 1 deletion Plotly.Blazor.Examples/Shared/CodeSnippet.razor
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@
{
if (firstRender)
{
Code = await CodeHttpClient.GetStringAsync(Url);
try
{
Code = await CodeHttpClient.GetStringAsync(Url);
}
catch
{
// ignore
}
StateHasChanged();
}
await JsRunTime.InvokeVoidAsync("onBlazorReady");
Expand Down
7 changes: 3 additions & 4 deletions Plotly.Blazor.Examples/Shared/NavMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
<MudPaper Class="d-flex flex-column overflow-x-auto pa-4 gap-4" Height="100vh">
@foreach (var pageInfo in pageInfos)
{
var uri = new Uri(NavManager.Uri);
var color = uri.AbsolutePath.TrimStart('/').Equals(pageInfo.Page.TrimStart('/')) ? Color.Primary : Color.Default;
var href = $"{NavManager.BaseUri}{pageInfo.Page}";
var uri = NavManager.BaseUri + pageInfo.Page;
var color = NavManager.Uri.Equals(uri, StringComparison.InvariantCultureIgnoreCase) ? Color.Primary : Color.Default;

<MudLink Class="d-flex" Color="@color" Typo="Typo.h4" Href="@href">@pageInfo.Title</MudLink>
<MudLink Class="d-flex" Color="@color" Typo="Typo.h4" Href="@uri">@pageInfo.Title</MudLink>
}
</MudPaper>

Expand Down
3 changes: 2 additions & 1 deletion Plotly.Blazor.Examples/Shared/NavMenu.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ private class PageInfo
new() { Page = "hover", Title = "Hover Event" },
new() { Page = "click", Title = "Click Event" },
new() { Page = "legendclick", Title = "Legend Click Event" },
new() { Page = "relayout", Title = "Relayout Event" }
new() { Page = "relayout", Title = "Relayout Event" },
new() { Page = "selected", Title = "Selected Event" }
};

private void OpenOrCloseDrawer()
Expand Down
2 changes: 1 addition & 1 deletion Plotly.Blazor.Generator/Plotly.Blazor.Generator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="src\wwwroot\plotly-interop-2.33.0.js">
<None Update="src\wwwroot\plotly-interop-5.1.0.js">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
Expand Down
2 changes: 1 addition & 1 deletion Plotly.Blazor.Generator/src/PlotlyJsInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Plotly.Blazor;
/// </summary>
public class PlotlyJsInterop
{
private const string InteropPath = "./_content/Plotly.Blazor/plotly-interop-2.33.0.js";
private const string InteropPath = "./_content/Plotly.Blazor/plotly-interop-5.1.0.js";
private const string PlotlyPath = "./_content/Plotly.Blazor/plotly-2.33.0.min.js";
private const string PlotlyBasicPath = "./_content/Plotly.Blazor/plotly-basic-1.58.5.min.js";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,42 @@ export function subscribeLegendClickEvent(dotNetObj, id) {
})
})
}
export function subscribeSelectedEvent(dotNetObj, id) {
var plot = document.getElementById(id);
plot.on('plotly_selected', function (data) {
dotNetObj.invokeMethodAsync('SelectedEvent',
data.points.map(function (d) {
if (d.x != null) {
return ({
TraceIndex: d.fullData.index,
PointIndex: d.pointIndex,
PointNumber: d.pointNumber,
CurveNumber: d.curveNumber,
Text: d.text,
X: d.x,
Y: d.y,
Z: d.z,
Lat: d.lat,
Lon: d.lon
});
}
else {
return ({
TraceIndex: d.fullData.index,
PointIndex: d.pointIndex,
PointNumber: d.pointNumber,
CurveNumber: d.curveNumber,
Text: d.text,
X: d.value,
Y: d.label,
Z: null,
Lat: d.lat,
Lon: d.lon
});
}
}));
})
}
export function subscribeClickEvent(dotNetObj, id) {
var plot = document.getElementById(id);
plot.on('plotly_click', function (data) {
Expand Down
26 changes: 26 additions & 0 deletions Plotly.Blazor/Plotly.Blazor.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23166,6 +23166,12 @@
Objects are currently required for accommodating different plot value types
</summary>
</member>
<member name="P:Plotly.Blazor.PlotlyChart.SelectedAction">
<summary>
Defines the action that should happen when the SelectedEvent is triggered.
Objects are currently required for accommodating different plot value types
</summary>
</member>
<member name="P:Plotly.Blazor.PlotlyChart.RelayoutAction">
<summary>
Defines the action that should happen when the RelayoutEvent is triggered.
Expand All @@ -23190,6 +23196,13 @@
</summary>
<param name = "eventData"></param>
</member>
<member name="M:Plotly.Blazor.PlotlyChart.SelectedEvent(System.Collections.Generic.IEnumerable{Plotly.Blazor.Interop.EventDataPoint})">
<summary>
Method which is called by JSRuntime once a you selected plot points, to invoke the passed in SelectedAction.
Objects are currently required for accommodating different plot value types.
</summary>
<param name = "eventData"></param>
</member>
<member name="M:Plotly.Blazor.PlotlyChart.RelayoutEvent(Plotly.Blazor.Interop.RelayoutEventData)">
<summary>
Method which is called by JSRuntime when the chart's layout has changed.
Expand All @@ -23216,6 +23229,13 @@
<param name = "cancellationToken">CancellationToken</param>
<returns>Task</returns>
</member>
<member name="M:Plotly.Blazor.PlotlyChart.SubscribeSelectedEvent(System.Threading.CancellationToken)">
<summary>
Subscribes to the selected event of the chart.
</summary>
<param name = "cancellationToken">CancellationToken</param>
<returns>Task</returns>
</member>
<member name="M:Plotly.Blazor.PlotlyChart.SubscribeRelayoutEvent(System.Threading.CancellationToken)">
<summary>
Subscribes to the relayout event of the chart.
Expand Down Expand Up @@ -23382,6 +23402,12 @@
</summary>
<param name="cancellationToken">CancellationToken</param>
</member>
<member name="M:Plotly.Blazor.PlotlyJsInterop.SubscribeSelectedEvent(System.Threading.CancellationToken)">
<summary>
Can be used to subscribe selected events for points.
</summary>
<param name="cancellationToken">CancellationToken</param>
</member>
<member name="M:Plotly.Blazor.PlotlyJsInterop.SubscribeRelayoutEvent(System.Threading.CancellationToken)">
<summary>
Can be used to subscribe to relayout events.
Expand Down
28 changes: 28 additions & 0 deletions Plotly.Blazor/PlotlyChart.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,13 @@ public async Task PrependTraces3D(IEnumerable<IEnumerable<object>> x, IEnumerabl
[Parameter]
public Action<IEnumerable<EventDataPoint>> HoverAction { get; set; }

/// <summary>
/// Defines the action that should happen when the SelectedEvent is triggered.
/// Objects are currently required for accommodating different plot value types
/// </summary>
[Parameter]
public Action<IEnumerable<EventDataPoint>> SelectedAction { get; set; }

/// <summary>
/// Defines the action that should happen when the RelayoutEvent is triggered.
/// </summary>
Expand Down Expand Up @@ -986,6 +993,17 @@ public void HoverEvent(IEnumerable<EventDataPoint> eventData)
HoverAction?.Invoke(eventData);
}

/// <summary>
/// Method which is called by JSRuntime once a you selected plot points, to invoke the passed in SelectedAction.
/// Objects are currently required for accommodating different plot value types.
/// </summary>
/// <param name = "eventData"></param>
[JSInvokable("SelectedEvent")]
public void SelectedEvent(IEnumerable<EventDataPoint> eventData)
{
SelectedAction?.Invoke(eventData);
}

/// <summary>
/// Method which is called by JSRuntime when the chart's layout has changed.
/// </summary>
Expand Down Expand Up @@ -1025,6 +1043,16 @@ public async Task SubscribeHoverEvent(CancellationToken cancellationToken = defa
await Interop.SubscribeHoverEvent(cancellationToken);
}

/// <summary>
/// Subscribes to the selected event of the chart.
/// </summary>
/// <param name = "cancellationToken">CancellationToken</param>
/// <returns>Task</returns>
public async Task SubscribeSelectedEvent(CancellationToken cancellationToken = default)
{
await Interop.SubscribeSelectedEvent(cancellationToken);
}

/// <summary>
/// Subscribes to the relayout event of the chart.
/// </summary>
Expand Down
13 changes: 12 additions & 1 deletion Plotly.Blazor/PlotlyJsInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Plotly.Blazor;
/// </summary>
public class PlotlyJsInterop
{
private const string InteropPath = "./_content/Plotly.Blazor/plotly-interop-2.33.0.js";
private const string InteropPath = "./_content/Plotly.Blazor/plotly-interop-5.1.0.js";
private const string PlotlyPath = "./_content/Plotly.Blazor/plotly-2.33.0.min.js";
private const string PlotlyBasicPath = "./_content/Plotly.Blazor/plotly-basic-1.58.5.min.js";

Expand Down Expand Up @@ -298,6 +298,17 @@ public async Task SubscribeHoverEvent(CancellationToken cancellationToken)
await jsRuntime.InvokeVoidAsync("subscribeHoverEvent", cancellationToken, dotNetObj, dotNetObj.Value.Id);
}

/// <summary>
/// Can be used to subscribe selected events for points.
/// </summary>
/// <param name="cancellationToken">CancellationToken</param>
public async Task SubscribeSelectedEvent(CancellationToken cancellationToken)
{
var jsRuntime = await moduleTask.Value;

await jsRuntime.InvokeVoidAsync("subscribeSelectedEvent", cancellationToken, dotNetObj, dotNetObj.Value.Id);
}

/// <summary>
/// Can be used to subscribe to relayout events.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,42 @@ export function subscribeLegendClickEvent(dotNetObj, id) {
})
})
}
export function subscribeSelectedEvent(dotNetObj, id) {
var plot = document.getElementById(id);
plot.on('plotly_selected', function (data) {
dotNetObj.invokeMethodAsync('SelectedEvent',
data.points.map(function (d) {
if (d.x != null) {
return ({
TraceIndex: d.fullData.index,
PointIndex: d.pointIndex,
PointNumber: d.pointNumber,
CurveNumber: d.curveNumber,
Text: d.text,
X: d.x,
Y: d.y,
Z: d.z,
Lat: d.lat,
Lon: d.lon
});
}
else {
return ({
TraceIndex: d.fullData.index,
PointIndex: d.pointIndex,
PointNumber: d.pointNumber,
CurveNumber: d.curveNumber,
Text: d.text,
X: d.value,
Y: d.label,
Z: null,
Lat: d.lat,
Lon: d.lon
});
}
}));
})
}
export function subscribeClickEvent(dotNetObj, id) {
var plot = document.getElementById(id);
plot.on('plotly_click', function (data) {
Expand Down Expand Up @@ -221,6 +257,9 @@ export function subscribeRelayoutEvent(dotNetObj, id) {
var y1 = data["yaxis.range[0]"]
var y2 = data["yaxis.range[1]"]

var z1 = data["zaxis.range[0]"]
var z2 = data["zaxis.range[1]"]

var result = {};

if (x1 && x2) {
Expand All @@ -230,6 +269,11 @@ export function subscribeRelayoutEvent(dotNetObj, id) {
if (y1 && y2) {
result.YRange = [y1, y2];
}

if (z1 && z2) {
result.ZRange = [z1, z2];
}

dotNetObj.invokeMethodAsync('RelayoutEvent', result);
});
}

0 comments on commit d604c58

Please sign in to comment.