diff --git a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts index 871c60a0a5..d3d32f3716 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts +++ b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts @@ -178,6 +178,13 @@ export class BrowserRenderer { toDomElement.addEventListener('click', listener); break; } + case 'onchange': { + toDomElement.removeEventListener('change', toDomElement['_blazorChangeListener']); + const listener = evt => raiseEvent(browserRendererId, componentId, eventHandlerId, 'change', { Type: 'change', Value: evt.target.value }); + toDomElement['_blazorChangeListener'] = listener; + toDomElement.addEventListener('change', listener); + break; + } case 'onkeypress': { toDomElement.removeEventListener('keypress', toDomElement['_blazorKeypressListener']); const listener = evt => { @@ -256,4 +263,4 @@ function raiseEvent(browserRendererId: number, componentId: number, eventHandler ]); } -type EventInfoType = 'mouse' | 'keyboard'; +type EventInfoType = 'mouse' | 'keyboard' | 'change'; diff --git a/src/Microsoft.AspNetCore.Blazor.Browser/Interop/Json.cs b/src/Microsoft.AspNetCore.Blazor.Browser/Interop/Json.cs index c2d3a3998b..8bb875742d 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser/Interop/Json.cs +++ b/src/Microsoft.AspNetCore.Blazor.Browser/Interop/Json.cs @@ -27,6 +27,8 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Interop private static object CoerceShallow(object deserializedValue, Type typeOfT) { + if (typeOfT == typeof(object)) { return deserializedValue; } + if (deserializedValue == null) { // Return default value for type diff --git a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs index 4799e94c65..aacb277f3f 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs +++ b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs @@ -36,6 +36,8 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering return Json.Deserialize(eventArgsJson); case "keyboard": return Json.Deserialize(eventArgsJson); + case "change": + return Json.Deserialize(eventArgsJson); default: throw new ArgumentException($"Unsupported value '{eventArgsType}'.", nameof(eventArgsType)); } diff --git a/src/Microsoft.AspNetCore.Blazor/Components/BlazorComponent.cs b/src/Microsoft.AspNetCore.Blazor/Components/BlazorComponent.cs index 8c30cec8ab..0943c57709 100644 --- a/src/Microsoft.AspNetCore.Blazor/Components/BlazorComponent.cs +++ b/src/Microsoft.AspNetCore.Blazor/Components/BlazorComponent.cs @@ -186,5 +186,14 @@ namespace Microsoft.AspNetCore.Blazor.Components protected RenderTreeFrame onclick(Action handler) // Note that the 'sequence' value is updated later when inserted into the tree => RenderTreeFrame.Attribute(0, "onclick", _ => handler()); + + /// + /// Handles change events by invoking . + /// + /// The handler to be invoked when the event occurs. The handler will receive the new value as a parameter. + /// A that represents the event handler. + protected RenderTreeFrame onchange(Action handler) + // Note that the 'sequence' value is updated later when inserted into the tree + => RenderTreeFrame.Attribute(0, "onchange", args => handler(((UIChangeEventArgs)args).Value)); } } diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/UIEventArgs.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/UIEventArgs.cs index 0c2635b327..abe4da6b83 100644 --- a/src/Microsoft.AspNetCore.Blazor/RenderTree/UIEventArgs.cs +++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/UIEventArgs.cs @@ -31,4 +31,16 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree /// public string Key { get; set; } } + + /// + /// Supplies information about an input change event that is being raised. + /// + public class UIChangeEventArgs : UIEventArgs + { + /// + /// Gets or sets the new value of the input. This may be a + /// or a . + /// + public object Value { get; set; } + } }