diff --git a/src/Core/Components/NumberField/FluentNumberField.razor.cs b/src/Core/Components/NumberField/FluentNumberField.razor.cs index 1543815bfc..4b369173df 100644 --- a/src/Core/Components/NumberField/FluentNumberField.razor.cs +++ b/src/Core/Components/NumberField/FluentNumberField.razor.cs @@ -6,7 +6,7 @@ namespace Microsoft.FluentUI.AspNetCore.Components; -public partial class FluentNumberField : FluentInputBase +public partial class FluentNumberField : FluentInputBase, IAsyncDisposable { private const string JAVASCRIPT_FILE = "./_content/Microsoft.FluentUI.AspNetCore.Components/Components/TextField/FluentTextField.razor.js"; @@ -166,12 +166,31 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender) { + Module ??= await JSRuntime.InvokeAsync("import", JAVASCRIPT_FILE.FormatCollocatedUrl(LibraryConfiguration)); + await Module.InvokeVoidAsync("ensureCurrentValueMatch", Element); + if (AutoComplete != null && !string.IsNullOrEmpty(Id)) { - Module ??= await JSRuntime.InvokeAsync("import", JAVASCRIPT_FILE.FormatCollocatedUrl(LibraryConfiguration)); await Module.InvokeVoidAsync("setControlAttribute", Id, "autocomplete", AutoComplete); } } } + + public async ValueTask DisposeAsync() + { + try + { + if (Module is not null) + { + await Module.DisposeAsync(); + } + } + catch (Exception ex) when (ex is JSDisconnectedException || + ex is OperationCanceledException) + { + // The JSRuntime side may routinely be gone already if the reason we're disposing is that + // the client disconnected. This is not an error. + } + } } diff --git a/src/Core/Components/Slider/FluentSlider.razor.cs b/src/Core/Components/Slider/FluentSlider.razor.cs index f9a162d34f..5c7765f65a 100644 --- a/src/Core/Components/Slider/FluentSlider.razor.cs +++ b/src/Core/Components/Slider/FluentSlider.razor.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Components; using Microsoft.FluentUI.AspNetCore.Components.Extensions; using Microsoft.FluentUI.AspNetCore.Components.Utilities; +using Microsoft.FluentUI.AspNetCore.Components.Utilities.InternalDebounce; using Microsoft.JSInterop; namespace Microsoft.FluentUI.AspNetCore.Components; @@ -27,7 +28,11 @@ public partial class FluentSlider : FluentInputBase, IAsyncDispo private TValue? max; private TValue? min; private bool updateSliderThumb = false; - private bool userChangedValue = false; + private DebounceAction Debounce { get; init; } + public FluentSlider() + { + Debounce = new DebounceAction(); + } /// /// Gets or sets the slider's minimal value. @@ -71,14 +76,7 @@ public override TValue? Value if (base.Value != value) { base.Value = value; - if (userChangedValue) - { - userChangedValue = false; - } - else - { - updateSliderThumb = true; - } + updateSliderThumb = true; } } } @@ -120,18 +118,15 @@ protected override async Task OnAfterRenderAsync(bool firstRender) updateSliderThumb = false; if (Module is not null) { - await Module!.InvokeVoidAsync("updateSlider", Element); + Debounce.Run(100, async () => + { + await Module!.InvokeVoidAsync("updateSlider", Element); + }); } } } } - protected override Task ChangeHandlerAsync(ChangeEventArgs e) - { - userChangedValue = true; - return base.ChangeHandlerAsync(e); - } - protected override string? ClassValue { get diff --git a/src/Core/Components/TextField/FluentTextField.razor.js b/src/Core/Components/TextField/FluentTextField.razor.js index 1f7b7844db..b09c81fe19 100644 --- a/src/Core/Components/TextField/FluentTextField.razor.js +++ b/src/Core/Components/TextField/FluentTextField.razor.js @@ -16,4 +16,21 @@ export function setDataList(id, datalistid) { shadowRoot.removeChild(shadowDataList); } shadowRoot.appendChild(dataList); -} \ No newline at end of file +} + +export function ensureCurrentValueMatch(ref) { + if (ref !== undefined && ref != null) { + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === "attributes") { + ref.value = mutation.target.getAttribute("value"); + } + }); + }); + observer.observe(ref, { + attributes: true, + attributeFilter: ["value"], + }); + } +} + diff --git a/tests/Core/NumberField/FluentNumberFieldTests.cs b/tests/Core/NumberField/FluentNumberFieldTests.cs index b07961f378..892ddb48f5 100644 --- a/tests/Core/NumberField/FluentNumberFieldTests.cs +++ b/tests/Core/NumberField/FluentNumberFieldTests.cs @@ -14,6 +14,7 @@ public class FluentNumberFieldTests : TestBase public FluentNumberFieldTests() { TestContext.Services.AddSingleton(LibraryConfiguration); + TestContext.JSInterop.Mode = JSRuntimeMode.Loose; } [Fact] diff --git a/tests/Core/Wizard/FluentWizardTests.razor b/tests/Core/Wizard/FluentWizardTests.razor index d15d0c96ac..077d58cedd 100644 --- a/tests/Core/Wizard/FluentWizardTests.razor +++ b/tests/Core/Wizard/FluentWizardTests.razor @@ -10,6 +10,7 @@ public FluentWizardTests() { this.Services.AddSingleton(LibraryConfiguration); + JSInterop.Mode = JSRuntimeMode.Loose; } [Fact]