OK, I'm sure I'm going mad and missing something simple here...
if I have an ElementReference
object in c# in a Blazor WASM app, how can I get any details about the html element which it is associated with?
I'm working on a Blazor WASM application, using .Net 6.0.
I am using a component library (SyncFusion) and with one of the components I need to determine which ListBox I'm dropping something into.
all I have is a Blazor ElementReference.
How do I get an HTML element from this object? I'm perfectly happy to use JSInterop for this, but since the ElementReference doesn't seem to have anything matching the generated HTML it's not really useful.
The component is rendering fine, and renders some stuff like:
<div id="listbox-a13426bc-6182-4b64-9c27-2fa57e97bcd2".....> </div>
In the events I'm getting from the component in question, I can get a Target
property which is a Blazor ElementReference
. This has an Id
which appears to be some automatically generated int value and is unique for each "List Box" generated, but I cannot work out how to match this to the specific component being referenced.
I have to be able to work out whether this refers to the right-side or left-side of two ListBoxes.
I can add additional Attributes or CSS classes to the controls in question but this doesn't help me as I can't work out how to match the ElementReference
or its Id
property to anything, when that's all I have to start with. I can also match the components up to a property reference with @ref="xxx"
but I have the same problem there.
The Component is an SfListBox
and that class doesn't seem to expose any way to retrieve the ElementReference for the associated HTML either so I can't pick it up and store it for later comparison either.
The ElementReference doesn't seem to have an obvious method or property to get the unique GUID it generated.
I've searched for a few hours trying to find the simple method I want, but I cannot find any obvious way to work this out....
Right, as hinted at by @fuzzybear the obvious solution to this is just to directly pass the ElementReference
through to a JS function via JSInterop, which will happily accept it as an HTMLElement
First, Define a JS function, in a nice unique namespace in index.html.
This function could check Id or other attributes of course, it's just JS stuff. In my case because I could quickly add CSS classes to the lists (see next step) I chose to write a function to check if a particular class is in the css classes for the element
<script>
var MyUtils = MyUtils || {};
MyUtils.hasClass = function (element, className) {
return element.classList.contains(className);
};
</script>
Next, in the blazor component....
ElementReference
you then need to just pass this to your JS function (in my case it was a DropEventHandler from my SyncFusion component)So my example code now looks something like this:
@inject IJSRuntime JS;
...(snip a bunch of other stuff)
<SfListBox
DataSource="@ItemList"
CssClass="left-box"
Scope="@Scope"
... (snip more properties etc)
>
<ListBoxEvents
TValue="TValue"
TItem="TItem"
OnDrop="SelectListDrop"
></ListBoxEvents>
</SfListBox>
@code{
...(snip other code)
async Task SelectListDrop(DropEventArgs<TItem> args)
{
//Here I can get an ElementReference from the passed-in args object
//Via the 'Target' property, so I pass this to my JS
//function via InvokeAsync.
var isLeft = await JS.InvokeAsync<bool>(
"MyUtils.hasClass",
new object[] { args.Target, "left-box" });
var targetBoxDesc = isLeft ? "left-box" : "right-box";
Console.WriteLine($"Target is {targetBoxDesc}");
}
}