Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bind-value-oninput throws #5521

Closed
Andrzej-W opened this issue May 11, 2018 · 21 comments
Closed

bind-value-oninput throws #5521

Andrzej-W opened this issue May 11, 2018 · 21 comments
Labels
area-blazor Includes: Blazor, Razor Components bug This issue describes a behavior which is not expected - a bug.

Comments

@Andrzej-W
Copy link

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:

  • binding which updates variable after every input field change
  • throttling - this is necessary if we want to do incremental search on the server or we have a big collection to filter; we should be able to specify a delay in milliseconds and our variable should be updated only after user stops typing for the specified period of time

I believe that throttling can be useful for other events also, for example mouse move, mouse wheel scrolling, etc.

@SteveSandersonMS
Copy link
Member

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.

@Andrzej-W
Copy link
Author

@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.

@SteveSandersonMS
Copy link
Member

Thanks. We'll have to review that.

@SteveSandersonMS SteveSandersonMS changed the title Add onkeypress with throttling behaviour to binding bind-value-oninput throws May 12, 2018
@Andrzej-W
Copy link
Author

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.

@L3tum
Copy link

L3tum commented Jun 24, 2018

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".

@ransagy
Copy link

ransagy commented Jul 5, 2018

That does work, great find. Is there any explanation for that part in documentation? dispatchEvent and CustomEvent, Specifically.

@Andrzej-W
Copy link
Author

Andrzej-W commented Jul 7, 2018

@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

@ransagy
Copy link

ransagy commented Jul 7, 2018

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.

sebbert referenced this issue in bemberas/Blazor Jul 31, 2018
Blazor does handle the oninput event, but it was marshalled as a regular UIEventArgs.
This meant that we didn't have access to the new value of the input element from our oninput handler.

Fixes #821
sebbert referenced this issue in bemberas/Blazor Jul 31, 2018
- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
sebbert referenced this issue in bemberas/Blazor Jul 31, 2018
- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
sebbert referenced this issue in bemberas/Blazor Jul 31, 2018
- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
SteveSandersonMS referenced this issue in dotnet/blazor Sep 24, 2018
- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
SteveSandersonMS referenced this issue in dotnet/blazor Nov 9, 2018
- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
SteveSandersonMS referenced this issue in dotnet/blazor Nov 9, 2018
- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
@stavroskasidis
Copy link

Thanks @L3tum, great workaround for now

SteveSandersonMS referenced this issue in dotnet/blazor Nov 12, 2018
- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
SteveSandersonMS referenced this issue in dotnet/blazor Nov 13, 2018
- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
SteveSandersonMS referenced this issue in dotnet/blazor Nov 13, 2018
- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
SteveSandersonMS referenced this issue in dotnet/blazor Nov 13, 2018
- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
SteveSandersonMS referenced this issue in dotnet/blazor Nov 13, 2018
* Marshal oninput events as UIChangeEventArgs

- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
SteveSandersonMS referenced this issue in SteveSandersonMS/BlazorMigration Nov 27, 2018
* Marshal oninput events as UIChangeEventArgs

- Blazor does handle the oninput event, but it is marshalled as a regular UIEventArgs
- This means that we cannot access the new value of the input element from inside our oninput handler

Addresses #821
@aspnet-hello aspnet-hello transferred this issue from dotnet/blazor Dec 17, 2018
@aspnet-hello aspnet-hello added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates bug This issue describes a behavior which is not expected - a bug. area-blazor Includes: Blazor, Razor Components labels Dec 17, 2018
@Andrzej-W
Copy link
Author

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.

@springy76
Copy link

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}.

@Andrzej-W
Copy link
Author

@springy76 it is probably not documented. I have just added this issue aspnet/Blazor.Docs#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.

@mkArtakMSFT
Copy link
Member

Thanks for contacting us.
@Andrzej-W, is there still a problem here or should this be closed now?

@Andrzej-W
Copy link
Author

@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: Unhandled 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

@danroth27
Copy link
Member

@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.

@PirasannaRavi
Copy link

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"; }

@guardrex
Copy link
Contributor

guardrex commented May 4, 2019

Hello @PirasannaRavi ... Please open product feedback over in the aspnet/AspNetCore issues.

@PirasannaRavi
Copy link

Sure @guardrex.
I created a new Issue as suggested.
https://github.com/aspnet/AspNetCore/issues/9974

@mkArtakMSFT mkArtakMSFT removed area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates labels May 9, 2019
@mvr-devs
Copy link

mvr-devs commented Jun 22, 2019

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

image

image

@guardrex
Copy link
Contributor

guardrex commented Jun 22, 2019

@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 👉 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 👉 dotnet/AspNetCore.Docs#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 👀 the details and API notes.

@mvr-devs
Copy link

Perfect !! Thanks so much !!

@dotnet dotnet locked as resolved and limited conversation to collaborators Dec 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components bug This issue describes a behavior which is not expected - a bug.
Projects
None yet
Development

No branches or pull requests