Replies: 2 comments 2 replies
-
So I am guessing we can use same strategy for onchange events just use regular JavaScript ? |
Beta Was this translation helpful? Give feedback.
-
Related to what @sbwalker posted and perhaps answering @vnetonline , I wanted to show a prototype of how I managed to create an "interactive" dropdown for static oqtane with minimal JavaScript and still being able to handle the callbacks. Essentially, I wrap the select element in a form with the usual stuff (data-enhance, antiforgery, ...) and I add an input of type submit that is not visible in the UI. Then, I bind the onchange of the select to click that invisible input that triggers the '@'onsubmit of the form, which is binded to a parameter callback. @namespace YourNamespace
@inherits ModuleControlBase
<form method="post" @formname="@FormName" @onsubmit="@OnSelected" data-enhance>
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input id="@($"{FormName}Submit")" type="submit" style="display: none;" />
<select id="@($"{FormName}Select")" class="form-select" name="@ValueName" onchange="document.getElementById('@($"{FormName}Submit")').click()">
@foreach (var element in SelectElements)
{
<option value="@element.Key" selected="@(element.Key == SelectedValue)">@element.Value</option>
}
</select>
</form>
@code {
public override string RenderMode => RenderModes.Static;
[Parameter]
public string FormName { get; set; } = "DropdownForm";
[Parameter]
public required Dictionary<string, string> SelectElements { get; set; }
[Parameter]
public required string SelectedValue { get; set; }
[Parameter]
public required string ValueName { get; set; }
[Parameter]
public EventCallback OnSelected { get; set; }
} As for the calling component, I need to define a public property annotated with the SupplyParameterFromForm, which will receive the value that was selected on the form when submitted and is accessible in the callback method. In my case, I needed to persist the selected value, so I ended up adding the value as a query string in the same page, which is then captured in the OnParametersSet. This private property (_sampleId) is also passed as a parameter to the component so that after the refresh, it correctly displays the selected element. @namespace YourNamespace
@inherits ModuleBase
@inject NavigationManager NavigationManager
<SubmittableDropdown FormName="@_sampleFormName"
SelectElements="@_sampleSelectOptions"
SelectedValue="@_sampleId.ToString()"
ValueName="@nameof(SampleId)"
OnSelected="SampleSelected">
</SubmittableDropdown>
<p>_sampleId: @_sampleId</p>
@code {
public override string RenderMode => RenderModes.Static;
[SupplyParameterFromForm(FormName = _sampleFormName)]
public int SampleId { get; set; }
private int _sampleId = 0;
private const string _sampleFormName = "SampleForm";
private string _sampleQueryString = "sample_id";
private Dictionary<string, string> _sampleSelectOptions = new Dictionary<string, string>()
{
{ "0", "Select a sample:" },
{ "1", "Sample 1" },
{ "2", "Sample 2" },
{ "3", "Sample 3" },
{ "4", "Sample 4" }
};
protected override void OnParametersSet()
{
if (PageState.QueryString.ContainsKey(_sampleQueryString))
{
_sampleId = Convert.ToInt32(PageState.QueryString[_sampleQueryString]);
}
}
private void SampleSelected()
{
NavigationManager.NavigateTo(SampleUrl());
}
private string SampleUrl()
{
Dictionary<string, string> query = new Dictionary<string, string>
{
{ _sampleQueryString, SampleId.ToString() }
};
return NavigateUrl(PageState.Route.PagePath, Utilities.CreateQueryString(query));
}
} This schema could be easily applied to "any" html element and "any" native event, without needing extra js and still being able to handle callbacks and values with C#. By the way, I wasn't able to submit the form with form.submit() as (iirc) it was triggering a full page reload, instead of an enhanced navigation, and that's why I ended up clicking the invisible input. I'd really appreciate any comments, suggestions or improvements about this prototype! |
Beta Was this translation helpful? Give feedback.
-
In one of my projects I need to create a module which uses Static Rendering but is also able to upload files. Currently the FileManager component relies on interactivity so it cannot be used in static module components. So I mocked up a quick demo... and it turns out that it is very easy to accomplish this using traditional JavaScript.
The main concept to understand is that although Static Blazor does not support @OnClick event handlers, you can use standard JavaScript onclick event handlers to process UI events.
The following code displays an HTML File Input and an Upload button. When the user clicks upload it calls an uploadFiles() JavaScript method (which is a simplified version of the Oqtane JS Interop uploadFiles() method) which chunks a file into smaller pieces and posts them to Oqtane's existing FileController API on the server (where they are reassembled).
Module component:
Module.js
Note that Oqtane's FileManager razor component contains a lot more functionality than this example as it is a folder/file picker, supports multiple progress indicators, and verifies that the file upload was successful. This example is simply intended to demonstrate how JavaScript can be easily used in Static Blazor.
Beta Was this translation helpful? Give feedback.
All reactions