Currently when we use <input bind="@myVariable" />
variable is updated when input field looses focus (onchange event is called). Popular requirement in many applications is to implement incremental search. To do this we need:
I believe that throttling can be useful for other events also, for example mouse move, mouse wheel scrolling, etc.
We already support binding to the input
event (e.g., bind-value-oninput=@myField
).
As for the throttling, that's an interesting question. For the short term at least I'd not want to complicate the event system with baking that in, at least not until there are more requests for it and we see the scenarios more broadly.
You can implement throttling yourself either by literally writing the code that throttles inside your event handler, or by using a library like Rx that has a built-in implementation. I know it's tricky to prevent redundant renders with this approach so we can keep considering it in the future if more people are requesting it often.
@SteveSandersonMS unfortunately your solution doesn't work. This code
<input bind-value-oninput="@FieldValue" />
<p>@FieldValue</p>
@functions{
string FieldValue { get; set; }
}
throws exception visible in console:
SCRIPT5022: System.InvalidCastException: Specified cast is not valid.
at Microsoft.AspNetCore.Blazor.Components.BindMethods+<>c__DisplayClass7_0.<SetValueHandler>b__0 (Microsoft.AspNetCore.Blazor.UIEventArgs _) <0x1c0c618 + 0x00014> in <0d9c96ffc9704aa9b088cbbe138126c6>:0
at Microsoft.AspNetCore.Blazor.Components.EventHandlerInvoker.Invoke (Microsoft.AspNetCore.Blazor.UIEventArgs e) <0x1c0c288 + 0x0008c> in <0d9c96ffc9704aa9b088cbbe138126c6>:0
at Microsoft.AspNetCore.Blazor.Components.BlazorComponent.Microsoft.AspNetCore.Blazor.Components.IHandleEvent.HandleEvent (Microsoft.AspNetCore.Blazor.Components.EventHandlerInvoker binding, Microsoft.AspNetCore.Blazor.UIEventArgs args) <0x1c0be10 + 0x0001a> in <0d9c96ffc9704aa9b088cbbe138126c6>:0
at Microsoft.AspNetCore.Blazor.Rendering.ComponentState.DispatchEvent (Microsoft.AspNetCore.Blazor.Components.EventHandlerInvoker binding, Microsoft.AspNetCore.Blazor.UIEventArgs eventArgs) <0x1c0bbb0 + 0x0003c> in <0d9c96ffc9704aa9b088cbbe138126c6>:0
at Microsoft.AspNetCore.Blazor.Rendering.Renderer.DispatchEvent (System.Int32 componentId, System.Int32 eventHandlerId, Microsoft.AspNetCore.Blazor.UIEventArgs eventArgs) <0x1c0b5e8 + 0x00054> in <0d9c96ffc9704aa9b088cbbe138126c6>:0
at Microsoft.AspNetCore.Blazor.Browser.Rendering.BrowserRenderer.DispatchBrowserEvent (System.Int32 componentId, System.Int32 eventHandlerId, Microsoft.AspNetCore.Blazor.UIEventArgs eventArgs) <0x1c0b480 + 0x00020> in <92ed9c6772a34798bccecc99cc26cbcd>:0
at Microsoft.AspNetCore.Blazor.Browser.Rendering.BrowserRendererEventDispatcher.DispatchEvent (System.String eventDescriptorJson, System.String eventArgsJson) <0x1bcb640 + 0x0005a> in <92ed9c6772a34798bccecc99cc26cbcd>:0
I can change oninput to onchange
<input bind-value-onchange="@FieldValue" />
and it works as standard binding.
Thanks. We'll have to review that.
It looks that bind-value-onchange is the only one which works. I have checked bind-value-onclick, bind-value-onkeypress, and a few more and I always see exceptions.
For anyone wondering, since as of right now (at least for me) with version 0.4.0 bind-value-oninput still throws I found another method to update the bound value.
<input placeholder="Search" autofocus autocomplete="on" oninput="(this.dispatchEvent(new CustomEvent('change', { bubbles: true })))" bind="@currentSearchTerm" />
The oninput function being the important part.
(Found this here).
Took me some time to find so thought I'd share it at the top result when googling "Blazor oninput".
That does work, great find. Is there any explanation for that part in documentation? dispatchEvent
and CustomEvent
, Specifically.
@ransagy
This
oninput="(this.dispatchEvent(new CustomEvent('change', { bubbles: true })))"
is not C# (Blazor) code. It is pure JavaScript. Look here:
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
Ah, I knew i had to be missing something. Thanks for the heads up. Here's hoping Blazor will get around to doing it on its own relatively quickly.
Thanks @L3tum, great workaround for now
I have just retested this bug in Blazor 0.7 and this code now works as expected:
<input bind-value-oninput="@FieldValue" />
<p>@FieldValue</p>
@functions{
string FieldValue { get; set; }
}
Unfortunately <input bind-value-onkeydown="@FieldValue" />
and <input bind-value-onkeyup="@FieldValue" />
throws Error: System.InvalidCastException: Specified cast is not valid.
Where can I read (in the docs) about bind-x-y
using 2 hyphens and what it actually does?
https://blazor.net/docs/components/index.html#data-binding only knows about bind-{property}
.
@springy76 it is probably not documented. I have just added this issue https://github.com/aspnet/Blazor.Docs/issues/368.
Standard syntax <input bind="@myVariable" />
is exactly the same as <input bind-value-onchange="@myVariable" />
which means: create two way data binding for value
property of input
element and update myVariable
each time onchange
event is fired. By analogy <input bind-value-oninput="@FieldValue" />
means that myVariable
will be updated each time oninput
event will be fired.
Thanks for contacting us.
@Andrzej-W, is there still a problem here or should this be closed now?
@mkArtakMSFT The problem with bind-value-oninput was fixed but if I want to use other events, for example bind-value-onkeydown, bind-value-onkeyup I'm still getting an exception. Currently I have the newest ASP.NET Core 3.0 Preview 4 and I see this in the browser's console:
WASM: 锘縐nhandled exception rendering component: blazor.webassembly.js:1:32082
WASM: System.ArgumentException: Object of type 'Microsoft.AspNetCore.Components.UIKeyboardEventArgs' cannot be converted to type 'Microsoft.AspNetCore.Components.UIChangeEventArgs'. blazor.webassembly.js:1:32082
WASM: at System.RuntimeType.CheckValue (System.Object value, System.Reflection.Binder binder, System.Globalization.CultureInfo culture, System.Reflection.BindingFlags invokeAttr) <0x1a505a0 + 0x000ca> in <46556de4d85b4f28892019a3d1d69868>:0 blazor.webassembly.js:1:32082
WASM: at System.Reflection.RuntimeMethodInfo.ConvertValues (System.Reflection.Binder binder, System.Object[] args, System.Reflection.ParameterInfo[] pinfo, System.Globalization.CultureInfo culture, System.Reflection.BindingFlags invokeAttr) <0x1a501d0 + 0x000f2> in <46556de4d85b4f28892019a3d1d69868>:0 blazor.webassembly.js:1:32082
WASM: at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) <0x1a4f698 + 0x00088> in <46556de4d85b4f28892019a3d1d69868>:0 blazor.webassembly.js:1:32082
WASM: at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) <0x1a4f128 + 0x00016> in <46556de4d85b4f28892019a3d1d69868>:0 blazor.webassembly.js:1:32082
WASM: at System.Delegate.DynamicInvokeImpl (System.Object[] args) <0x200a348 + 0x0019e> in <46556de4d85b4f28892019a3d1d69868>:0 blazor.webassembly.js:1:32082
WASM: at System.MulticastDelegate.DynamicInvokeImpl (System.Object[] args) <0x200a0e0 + 0x00016> in <46556de4d85b4f28892019a3d1d69868>:0 blazor.webassembly.js:1:32082
WASM: at System.Delegate.DynamicInvoke (System.Object[] args) <0x2009fe8 + 0x0000c> in <46556de4d85b4f28892019a3d1d69868>:0 blazor.webassembly.js:1:32082
WASM: at Microsoft.AspNetCore.Components.EventCallbackWorkItem.InvokeAsync[T] (System.MulticastDelegate delegate, T arg) <0x2009dc0 + 0x000cc> in <b90d61056671486d8836d104b91086c9>:0 blazor.webassembly.js:1:32082
WASM: at Microsoft.AspNetCore.Components.EventCallbackWorkItem.InvokeAsync (System.Object arg) <0x2009a90 + 0x0000c> in <b90d61056671486d8836d104b91086c9>:0 blazor.webassembly.js:1:32082
WASM: at Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync (Microsoft.AspNetCore.Components.EventCallbackWorkItem callback, System.Object arg) <0x20099f8 + 0x0000a> in <b90d61056671486d8836d104b91086c9>:0 blazor.webassembly.js:1:32082
WASM: at Microsoft.AspNetCore.Components.EventCallback.InvokeAsync (System.Object arg) <0x20095e8 + 0x00046> in <b90d61056671486d8836d104b91086c9>:0 blazor.webassembly.js:1:32082
WASM: at Microsoft.AspNetCore.Components.Rendering.Renderer.DispatchEventAsync (System.Int32 eventHandlerId, Microsoft.AspNetCore.Components.UIEventArgs eventArgs) <0x2008f08 + 0x0005a> in <b90d61056671486d8836d104b91086c9>:0 blazor.webassembly.js:1:32082
Error: System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.AspNetCore.Components.Rendering.Renderer.GetErrorHandledTask (System.Threading.Tasks.Task taskToHandle) <0x2043c48 + 0x00112> in <b90d61056671486d8836d104b91086c9>:0 blazor.webassembly.js:1:6160
@Andrzej-W onkeydown
and onkeyup
don't actually provide the value, so the behavior described is expected. @guardrex We should document this better. We may also look at improving this experience as we look at adding support for directive attributes.
Closing as we don't think there is anything left to do here.
https://github.com/aspnet/Blazor/issues/1235#issuecomment-489328205
bind-value-oninput
or bind
does not work with contenteditable
divs.
In the below code, the expectation is as and when I edit the div content I need to update the model so that I can then later save it back.
<div contenteditable="true" bind-value-oninput="@contentEditableText">
You can Edit this Text
</div>
@contentEditableText
@functions { string contentEditableText = "You can Edit this Text"; }
Hello @PirasannaRavi ... Please open product feedback over in the aspnet/AspNetCore issues.
Sure @guardrex.
I created a new Issue as suggested.
https://github.com/aspnet/AspNetCore/issues/9974
bind-value-oninput does not throw an exception but it also does not update the variable as of version 3.0.0-preview6.19307.2
<div class="search-bar">
<input bind-value-oninput="@SearchTerm" oninput="@(()=>PreformSearch())" placeholder="search for customers or tickets" />.
</div>
@code {
private string SearchTerm { get; set; }
private void PreformSearch()
{
Console.WriteLine($"Something tells me you are trying to search for '{SearchTerm}' ...");
}
}
This results in the following in the console window
@mvr-devs Try this ...
<div class="search-bar">
<input @oninput="@PreformSearch" placeholder="search for customers or tickets" />
</div>
@code {
private void PreformSearch(UIChangeEventArgs e)
{
Console.WriteLine($"Something tells me you are trying to search for '{e.Value}' ...");
}
}
The events are covered here :point_right: https://docs.microsoft.com/aspnet/core/blazor/components?view=aspnetcore-3.0#event-handling
... _BUT_ ... I'm working on a nicer presentation and showing all of them here :point_right: https://github.com/aspnet/AspNetCore.Docs/pull/12929 ... and the link you see in that new coverage (https://github.com/aspnet/AspNetCore/blob/master/src/Components/Components/src/UIEventArgs.cs) will get you to the reference source, so you can really :eyes: the details and API notes.
Perfect !! Thanks so much !!
Most helpful comment
For anyone wondering, since as of right now (at least for me) with version 0.4.0 bind-value-oninput still throws I found another method to update the bound value.
<input placeholder="Search" autofocus autocomplete="on" oninput="(this.dispatchEvent(new CustomEvent('change', { bubbles: true })))" bind="@currentSearchTerm" />
The oninput function being the important part.
(Found this here).
Took me some time to find so thought I'd share it at the top result when googling "Blazor oninput".