Fix selection on <select> box. Fixes #157
This commit is contained in:
parent
03ac95f086
commit
a02ac60c8c
|
|
@ -2,6 +2,7 @@
|
||||||
import { getRenderTreeEditPtr, renderTreeEdit, RenderTreeEditPointer, EditType } from './RenderTreeEdit';
|
import { getRenderTreeEditPtr, renderTreeEdit, RenderTreeEditPointer, EditType } from './RenderTreeEdit';
|
||||||
import { getTreeFramePtr, renderTreeFrame, FrameType, RenderTreeFramePointer } from './RenderTreeFrame';
|
import { getTreeFramePtr, renderTreeFrame, FrameType, RenderTreeFramePointer } from './RenderTreeFrame';
|
||||||
import { platform } from '../Environment';
|
import { platform } from '../Environment';
|
||||||
|
const selectValuePropname = '_blazorSelectValue';
|
||||||
let raiseEventMethod: MethodHandle;
|
let raiseEventMethod: MethodHandle;
|
||||||
let renderComponentMethod: MethodHandle;
|
let renderComponentMethod: MethodHandle;
|
||||||
|
|
||||||
|
|
@ -226,8 +227,24 @@ export class BrowserRenderer {
|
||||||
if (isCheckbox(element)) {
|
if (isCheckbox(element)) {
|
||||||
(element as HTMLInputElement).checked = value === 'True';
|
(element as HTMLInputElement).checked = value === 'True';
|
||||||
} else {
|
} else {
|
||||||
// Note: this doen't handle <select> correctly: https://github.com/aspnet/Blazor/issues/157
|
|
||||||
(element as any).value = value;
|
(element as any).value = value;
|
||||||
|
|
||||||
|
if (element.tagName === 'SELECT') {
|
||||||
|
// <select> is special, in that anything we write to .value will be lost if there
|
||||||
|
// isn't yet a matching <option>. To maintain the expected behavior no matter the
|
||||||
|
// element insertion/update order, preserve the desired value separately so
|
||||||
|
// we can recover it when inserting any matching <option>.
|
||||||
|
element[selectValuePropname] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case 'OPTION':
|
||||||
|
element.setAttribute('value', value!);
|
||||||
|
// See above for why we have this special handling for <select>/<option>
|
||||||
|
const parentElement = element.parentElement;
|
||||||
|
if (parentElement && (selectValuePropname in parentElement) && parentElement[selectValuePropname] === value) {
|
||||||
|
this.tryApplyValueProperty(parentElement, value);
|
||||||
|
delete parentElement[selectValuePropname];
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using BasicTestApp;
|
||||||
using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure;
|
using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure.ServerFixtures;
|
using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure.ServerFixtures;
|
||||||
using OpenQA.Selenium;
|
using OpenQA.Selenium;
|
||||||
|
using OpenQA.Selenium.Support.UI;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.E2ETest.Tests
|
namespace Microsoft.AspNetCore.Blazor.E2ETest.Tests
|
||||||
|
|
@ -74,5 +75,25 @@ namespace Microsoft.AspNetCore.Blazor.E2ETest.Tests
|
||||||
Assert.False(target.Selected);
|
Assert.False(target.Selected);
|
||||||
Assert.Equal("False", boundValue.Text);
|
Assert.Equal("False", boundValue.Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanBindSelect()
|
||||||
|
{
|
||||||
|
var target = new SelectElement(Browser.FindElement(By.Id("select-box")));
|
||||||
|
var boundValue = Browser.FindElement(By.Id("select-box-value"));
|
||||||
|
Assert.Equal("Second choice", target.SelectedOption.Text);
|
||||||
|
Assert.Equal("Second", boundValue.Text);
|
||||||
|
|
||||||
|
// Modify target; verify value is updated
|
||||||
|
target.SelectByText("Third choice");
|
||||||
|
Assert.Equal("Third", boundValue.Text);
|
||||||
|
|
||||||
|
// Also verify we can add and select new options atomically
|
||||||
|
// Don't move this into a separate test, because then the previous assertions
|
||||||
|
// would be dependent on test execution order (or would require a full page reload)
|
||||||
|
Browser.FindElement(By.Id("select-box-add-option")).Click();
|
||||||
|
Assert.Equal("Fourth", boundValue.Text);
|
||||||
|
Assert.Equal("Fourth choice", target.SelectedOption.Text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,35 @@
|
||||||
<span id="checkbox-initially-checked-value">@checkboxInitiallyCheckedValue</span>
|
<span id="checkbox-initially-checked-value">@checkboxInitiallyCheckedValue</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h2>Select</h2>
|
||||||
|
<p>
|
||||||
|
<select id="select-box" @bind(selectValue)>
|
||||||
|
<option value=@SelectableValue.First>First choice</option>
|
||||||
|
<option value=@SelectableValue.Second>Second choice</option>
|
||||||
|
<option value=@SelectableValue.Third>Third choice</option>
|
||||||
|
@if (includeFourthOption)
|
||||||
|
{
|
||||||
|
<option value=@SelectableValue.Fourth>Fourth choice</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
<span id="select-box-value">@selectValue</span>
|
||||||
|
<button id="select-box-add-option" @onclick(AddAndSelectNewSelectOption)>Add and select new item</button>
|
||||||
|
</p>
|
||||||
|
|
||||||
@functions {
|
@functions {
|
||||||
string textboxInitiallyBlankValue = null;
|
string textboxInitiallyBlankValue = null;
|
||||||
string textboxInitiallyPopulatedValue = "Hello";
|
string textboxInitiallyPopulatedValue = "Hello";
|
||||||
|
|
||||||
bool checkboxInitiallyUncheckedValue = false;
|
bool checkboxInitiallyUncheckedValue = false;
|
||||||
bool checkboxInitiallyCheckedValue = true;
|
bool checkboxInitiallyCheckedValue = true;
|
||||||
|
|
||||||
|
bool includeFourthOption = false;
|
||||||
|
enum SelectableValue { First, Second, Third, Fourth }
|
||||||
|
SelectableValue selectValue = SelectableValue.Second;
|
||||||
|
|
||||||
|
void AddAndSelectNewSelectOption()
|
||||||
|
{
|
||||||
|
includeFourthOption = true;
|
||||||
|
selectValue = SelectableValue.Fourth;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue