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

Blazor WebAssembly / EditForm / OnValidSubmit event error #24139

Closed
dotnetspark opened this issue Jul 21, 2020 · 10 comments
Closed

Blazor WebAssembly / EditForm / OnValidSubmit event error #24139

dotnetspark opened this issue Jul 21, 2020 · 10 comments
Assignees
Labels
area-blazor Includes: Blazor, Razor Components feature-blazor-wasm This issue is related to and / or impacts Blazor WebAssembly ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. Status: Resolved
Milestone

Comments

@dotnetspark
Copy link

I have a sample app which basically as I type autocompletes results from Azure CosmosDB. The Autocomplete razor file is a modified version of the one here. For some reason if I submit the EditForm from Index.razor I get the error below (Console Output).

Autocomplete.razor

@using SampleCosmosDB.Components
@inherits InputText

<input @bind="BoundValue" @bind:event="oninput" @onblur="Hide" autocomplete="off" @attributes="@AdditionalAttributes" class="@CssClass" />

<div role="listbox" class="autocomplete-suggestions @(visible ? "visible" : "")">
    @foreach (var choice in currentChoices.Take(3))
    {
        <div role="option" @onclick="() => ChooseAsync(choice)">@choice.Name</div>
    }
</div>

@code {
    bool visible;
    AutocompleteProductItem[] currentChoices = Array.Empty<AutocompleteProductItem>();

    [Parameter] public Func<string, Task<IEnumerable<AutocompleteProductItem>>> Choices { get; set; }
    [Parameter] public EventCallback<string> OnItemChosen { get; set; }

    string BoundValue
    {
        get => CurrentValueAsString;
        set
        {
            CurrentValueAsString = value;
            _ = UpdateAutocompleteOptionsAsync();
        }
    }

    async Task UpdateAutocompleteOptionsAsync()
    {
        if (EditContext.GetValidationMessages(FieldIdentifier).Any())
        {
            // If the input is invalid, don't show any autocomplete options
            currentChoices = Array.Empty<AutocompleteProductItem>();
        }
        else
        {
            var valueSnapshot = CurrentValueAsString;
            var suppliedChoices = (await Choices(valueSnapshot)).ToArray();

            // By the time we get here, the user might have typed other characters
            // Only use the result if this still represents the latest entry
            if (CurrentValueAsString == valueSnapshot)
            {
                currentChoices = suppliedChoices;
                visible = currentChoices.Any();
                StateHasChanged();
            }
        }
    }

    void Hide() => visible = false;

    Task ChooseAsync(AutocompleteProductItem choice)
    {
        CurrentValueAsString = choice.Name;
        Hide();
        return OnItemChosen.InvokeAsync(choice.Id);
    }
}

AutocompleteProductItem

namespace SampleCosmosDB.Components
{
    public class AutocompleteProductItem
    {
        public string Id { get; set; }
        public string Name { get; set; }
    }
}

Index.razor

@page "/"
@using Microsoft.Extensions.Localization
@using SampleCosmosDB.Components
@using Microsoft.Azure.Cosmos
@using Microsoft.Azure.Cosmos.Linq
@using System.Linq
@inject NavigationManager Navigation
@inject IStringLocalizer<App> Localize

<main class="container">
    <EditForm class="home-options" Model="this" OnValidSubmit="FindProduct">
        <DataAnnotationsValidator />

        <p>@Localize["EnterProductName"]</p>
        <Autocomplete @bind-Value="@ProductName" 
                       Choices="@GetProductNameAutocompleteItems"
                       OnItemChosen="EditProduct" 
                       class="find-by-product-name" 
                       placeholder="@Localize["ProductNamePlaceHolder"]" />
        <ValidationMessage For="() => ProductName" />
    </EditForm>
</main>

@code {
    public string ProductName { get; set; }

    async Task<IEnumerable<AutocompleteProductItem>> GetProductNameAutocompleteItems(string prefix)
    {
        var endpoint = "https://mycosmosendpoint.documents.azure.com:443/";
        var authKey = "myAuthkey";
        var cosmosClientOptions = new CosmosClientOptions
        {
            ConnectionMode = ConnectionMode.Gateway
        };

        var autocompleteProductItems = new List<AutocompleteProductItem>();
        using (var cosmosClient = new CosmosClient(endpoint, authKey, cosmosClientOptions))
        {
            var container = cosmosClient.GetContainer("ProductsDataStore", "Products");
            var iterator = container
                .GetItemLinqQueryable<IDictionary<string, string>>(true)
                .Where(m => m["name"].Contains(prefix))
                .ToFeedIterator();

            while (iterator.HasMoreResults)
            {
                autocompleteProductItems.AddRange(
                    from document in await iterator.ReadNextAsync()
                    select new AutocompleteProductItem {Id = document["id"], Name = document["name"]});
            }
        }

        return autocompleteProductItems;
    }

    void EditProduct(string id)
    {
        if (!string.IsNullOrEmpty(id))
        {
            Navigation.NavigateTo($"product/{id}");
        }
    }

    void FindProduct()
    {
        Navigation.NavigateTo("product/view/3");
    }
}

ViewProduct.razor

@page "/product/view/{id}"

<h3>View Product @Id</h3>

@code {
    [Parameter] public string Id { get; set; }
}

Console Output

image

@mkArtakMSFT mkArtakMSFT added area-blazor Includes: Blazor, Razor Components feature-blazor-wasm This issue is related to and / or impacts Blazor WebAssembly labels Jul 21, 2020
@mrpmorris
Copy link

mrpmorris commented Jul 21, 2020

Because you don't (can't) await the async method you execute from your property setter it takes place independently of the current chain of execution.

In this case, use InvokeAsync(StateHasChanged)

@dotnetspark
Copy link
Author

@mrpmorris if I understand should be like this,

if (CurrentValueAsString == valueSnapshot)
{
	currentChoices = suppliedChoices;
	visible = currentChoices.Any();
	InvokeAsync(StateHasChanged);
}

just did it and still get the same error.

@ghost
Copy link

ghost commented Jul 21, 2020

Thanks for contacting us.
We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We will evaluate the request when we are planning the work for the next milestone. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@dotnetspark
Copy link
Author

Just following up. Is there any news about this issue?

@SteveSandersonMS
Copy link
Member

This is currently in our "Next spring planning" milestone while means we'll be deciding whether to investigate it next time we do a sprint planning session, which is normally once per month.

We may need a more minimal repro in order to investigate it. Are you able to amend your repro code so that it doesn't require external dependencies such as CosmoDB? Thanks!

Additionally, could you please verify whether the same problem still exists in .NET 5 preview? We did fix two issues whereby concurrent/overlapping events would cause this particular error, so I'd say there's a good chance this is already fixed.

@dotnetspark
Copy link
Author

Hi @SteveSandersonMS. I just upgraded to RC1. I'm sure it'll work now. I just can't confirm because of the following error. I'm going to open an issue about that.
image

@dotnetspark
Copy link
Author

Just a follow up. I opened #26043, and Azure Cosmos SDK had a bug, which has been fixed by Azure/azure-cosmos-dotnet-v3/pull/1863. I just learned this update should be available by next week. Helpfully, I'd be able to test by then.

@pranavkm
Copy link
Contributor

@ylr-research looks like your issue has been resolved. Feel free to file a new issue if there is anything more for us to address.

@pranavkm pranavkm added ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. and removed investigate labels Sep 23, 2020
@ghost ghost added the Status: Resolved label Sep 23, 2020
@dotnetspark
Copy link
Author

@pranavkm What should I do in order to test?

@ghost
Copy link

ghost commented Sep 24, 2020

This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes.

See our Issue Management Policies for more information.

@ghost ghost closed this as completed Sep 24, 2020
ASP.NET Core Blazor & MVC 5.0.x automation moved this from 5.0 GA to Done Sep 24, 2020
@dotnet dotnet locked as resolved and limited conversation to collaborators Oct 24, 2020
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components feature-blazor-wasm This issue is related to and / or impacts Blazor WebAssembly ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. Status: Resolved
Projects
No open projects
Development

No branches or pull requests

6 participants