Blazored / Typeahead

Typeahead control for Blazor applications
https://blazored.github.io/Typeahead/
MIT License
440 stars 103 forks source link

Gettingerror : equires a ConvertMethod parameter. #137

Closed nssidhu closed 4 years ago

nssidhu commented 4 years ago

blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Blazored.Typeahead.BlazoredTypeahead2[DbModels.CountryCodes,System.String] requires a ConvertMethod parameter. System.InvalidOperationException: Blazored.Typeahead.BlazoredTypeahead2[DbModels.CountryCodes,System.String] requires a ConvertMethod parameter. at Blazored.Typeahead.BlazoredTypeahead`2[TItem,TValue].OnInitialized () <0x382bcb0 + 0x00060> in :0 at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync () <0x2e5b380 + 0x00030> in :0

This is EF generated Class DbModel Class

public partial class CountryCodes
    {
        public Guid Id { get; set; }
        public string CountryCode2 { get; set; }
        public string CountryCode3 { get; set; }
        public string CountryName { get; set; }
        public string CapitalName { get; set; }
    }

Editprofile.razor

<AuthorizeView>
    <NotAuthorized>
        <h3> You have reached a Page that is only avalable to Logged in user</h3>
    </NotAuthorized>

    <Authorized Context="authContext">
        <EditForm Model="_editprofileModel" OnValidSubmit="UpdateProfile">
            <FluentValidator TValidator="EditProfileValidator" />
            <ValidationSummary />

            <div class="card ">
                <div class="card-header">Edit Profile</div>
                <div class="card-body">

                    <div class="row">
                        <div class="col col-auto">
                            <div class="form-group">
                                <label for="countryName" class="control-label">CountryName</label>
                                <input type="text" id="countryName" @bind="_editprofileModel.CountryName" class="form-control" />

                                <BlazoredTypeahead SearchMethod="@SearchCountries"
                                                   @bind-Value="_editprofileModel.CountryName"
                                                   Debounce="500">
                                    <SelectedTemplate Context="countryList" >
                                        @_editprofileModel.CountryName
                                    </SelectedTemplate>
                                    <ResultTemplate Context="countryList">
                                        @countryList.CountryName
                                    </ResultTemplate>
                                    <NotFoundTemplate>
                                        Sorry, there weren't any search results.
                                    </NotFoundTemplate>
                                </BlazoredTypeahead>
                                <ValidationMessage For="@(() => _editprofileModel.CountryName)" />
                            </div>
                        </div>
                        <div class="col col-auto">
                            <div class="form-group">
                                <label for="cellphone" class="control-label">Cell Phone</label>
                                <input type="text" id="cellphone" @bind="_editprofileModel.CellPhone" class="form-control" />
                                <ValidationMessage For="@(() => _editprofileModel.CellPhone)" />
                            </div>
                        </div>

                    </div>

                    @if (!messageStatus.hide)
                    {
                        <div class="row">
                            <div class="alert @messageStatus.cssClass" role="alert">@messageStatus.Message</div>
                        </div>
                    }
                </div>

                <div class="card-footer text-muted">
                    <div class="d-flex flex-row">
                        <div class="col-auto">   <input class="btn btn-success" type="submit" value="Update Profile" /></div>
                    </div>

                </div>

            </div>

        </EditForm>
    </Authorized>

</AuthorizeView>

@code{

  [Parameter] public IEnumerable<DbModels.CountryCodes> countryList { get; set; }

    private async Task<IEnumerable<DbModels.CountryCodes>> SearchCountries(string searchCountryText)
    {
        var response = await _http.GetAsync($"Utility/GetListOfCountries?searchCountriesText={searchCountryText}");

        if (response.IsSuccessStatusCode)
        {
            var countryList = response.Content.ReadFromJsonAsync<List<CountryCodes>>().Result;
        }
        return  await Task.FromResult(countryList);
    }
}

WebAPI method

  ```

[HttpGet] [HttpOptions] [AllowAnonymous] [Produces("application/json")] public async Task GetListOfCountries(string searchCountriesText) { if (string.IsNullOrEmpty(searchCountriesText)) { return BadRequest(new { message = "Missing required parameter (searchCountriesText) ", currentDate = DateTime.Now }); }

        var countylist = _dbContext.CountryCodes.Where(c => c.CountryName.Contains(searchCountriesText)).ToList();

            if (countylist == null)
            {
                IActionResult resp = BadRequest(new { message = "No countries were found", currentDate = DateTime.Now });
                // IActionResult resp = BadRequest(new { Ok = false, ReasonPhrase = "This email is already registered" });
                return resp;
            }

        var response = Ok(new { countries = countylist });

        return response;
    }
chrissainty commented 4 years ago

As the message states, you need to provide a convert method as, I'm assuming, your binding a string value in your form _editprofileModel.CountryName but you're providing a list of CountryCodes. You need to tell the Typeahead how to map whatever the value is in your form to a country code.

If you have a look in the readme there is an explanation there.

Kurti123 commented 3 years ago

Today I stumbled over the same problem and the readme doesn't help me, I think due to my lack of expertise with blazor... I don't really understand what exactly to do here...

"you can achieve this by providing a convertMethod" .... but where exactly do i provide this method? As a beginner, I would assume something like this:

<SelectedTemplate @onselect="@(() => Convert(@context))">
    @context
</SelectedTemplate>

image

chrissainty commented 3 years ago

@Kurti123 If you look at the sample projects there is an example of how to use the convert method:

https://github.com/Blazored/Typeahead/blob/main/samples/BlazorWebAssembly/Pages/Index.razor

I appreciate the readme isn't the best on this topic. I've raised an issue to update it - #185.

Kurti123 commented 3 years ago

Ah I could figure it out with the examples. Thank you!

Tshifhiwa-AOLC commented 2 years ago

Hi @chrissainty. may you please add some ccomment on your code.