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 d3d32f3716..c457a659bc 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts +++ b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts @@ -168,19 +168,25 @@ export class BrowserRenderer { const browserRendererId = this.browserRendererId; const eventHandlerId = renderTreeFrame.attributeEventHandlerId(attributeFrame); + if (attributeName === 'value') { + if (this.tryApplyValueProperty(toDomElement, renderTreeFrame.attributeValue(attributeFrame))) { + return; // If this DOM element type has special 'value' handling, don't also write it as an attribute + } + } + // TODO: Instead of applying separate event listeners to each DOM element, use event delegation // and remove all the _blazor*Listener hacks switch (attributeName) { case 'onclick': { toDomElement.removeEventListener('click', toDomElement['_blazorClickListener']); - const listener = () => raiseEvent(browserRendererId, componentId, eventHandlerId, 'mouse', { Type: 'click' }); + const listener = evt => raiseEvent(evt, browserRendererId, componentId, eventHandlerId, 'mouse', { Type: 'click' }); toDomElement['_blazorClickListener'] = listener; 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 }); + const listener = evt => raiseEvent(evt, browserRendererId, componentId, eventHandlerId, 'change', { Type: 'change', Value: evt.target.value }); toDomElement['_blazorChangeListener'] = listener; toDomElement.addEventListener('change', listener); break; @@ -192,7 +198,7 @@ export class BrowserRenderer { // just to establish that we can pass parameters when raising events. // We use C#-style PascalCase on the eventInfo to simplify deserialization, but this could // change if we introduced a richer JSON library on the .NET side. - raiseEvent(browserRendererId, componentId, eventHandlerId, 'keyboard', { Type: evt.type, Key: (evt as any).key }); + raiseEvent(evt, browserRendererId, componentId, eventHandlerId, 'keyboard', { Type: evt.type, Key: (evt as any).key }); }; toDomElement['_blazorKeypressListener'] = listener; toDomElement.addEventListener('keypress', listener); @@ -208,6 +214,18 @@ export class BrowserRenderer { } } + tryApplyValueProperty(element: Element, value: string | null) { + // Certain elements have built-in behaviour for their 'value' property + switch (element.tagName) { + case 'INPUT': + case 'SELECT': // Note: this doen't handle { uri = (string)value; }) size="60"/> +

+ +

+

Method:
+ +

+ +

+

Request body:
+ +

+ +

+

Request headers:
+ @foreach (var header in requestHeaders) + { +
+ Name: { header.Name = (string)value; }) /> + Value: { header.Value = (string)value; }) /> + [ RemoveHeader(header))>remove] +
+ } + +

+ + + +@if (responseStatusCode.HasValue) +{ +

Response

+

Status:
@responseStatusCode

+

Body:

+

Headers:

+} + + + +@functions { + string uri = "http://api.icndb.com/jokes/random"; + string method = "GET"; + string requestBody = ""; + List requestHeaders = new List(); + + HttpStatusCode? responseStatusCode; + string responseBody; + string responseHeaders; + + async void DoRequest() + { + responseStatusCode = null; + + try + { + var requestMessage = new HttpRequestMessage() + { + Method = new HttpMethod(method), + RequestUri = new Uri(uri), + Content = string.IsNullOrEmpty(requestBody) + ? null + : new StringContent(requestBody) + }; + + foreach (var header in requestHeaders) + { + if (!requestMessage.Headers.TryAddWithoutValidation(header.Name, header.Value)) + { + requestMessage.Content?.Headers.TryAddWithoutValidation(header.Name, header.Value); + } + } + + var response = await Http.SendAsync(requestMessage); + responseStatusCode = response.StatusCode; + responseBody = await response.Content.ReadAsStringAsync(); + var allHeaders = response.Headers.Concat(response.Content?.Headers + ?? Enumerable.Empty>>()); + responseHeaders = string.Join( + Environment.NewLine, + allHeaders.Select(pair => $"{pair.Key}: {pair.Value.First()}").ToArray()); + } + catch (Exception ex) + { + if (ex is AggregateException) + { + ex = ex.InnerException; + } + responseStatusCode = HttpStatusCode.SeeOther; + responseBody = ex.Message + Environment.NewLine + ex.StackTrace; + } + + StateHasChanged(); + } + + void AddHeader() + => requestHeaders.Add(new RequestHeader()); + + void RemoveHeader(RequestHeader header) + => requestHeaders.Remove(header); + + class RequestHeader + { + public string Name { get; set; } + public string Value { get; set; } + } +} diff --git a/test/testapps/BasicTestApp/RouterTest/TestRouter.cshtml b/test/testapps/BasicTestApp/RouterTest/TestRouter.cshtml index c628df304d..7f16328038 100644 --- a/test/testapps/BasicTestApp/RouterTest/TestRouter.cshtml +++ b/test/testapps/BasicTestApp/RouterTest/TestRouter.cshtml @@ -1,4 +1,4 @@ @using Microsoft.AspNetCore.Blazor.Routing + PagesNamespace=@nameof(BasicTestApp) + DefaultComponentName=@("Default") /> diff --git a/test/testapps/BasicTestApp/wwwroot/index.html b/test/testapps/BasicTestApp/wwwroot/index.html index 97a440d873..c0e976bb97 100644 --- a/test/testapps/BasicTestApp/wwwroot/index.html +++ b/test/testapps/BasicTestApp/wwwroot/index.html @@ -6,16 +6,44 @@ + + Loading...