简体   繁体   中英

Cascading dropdown form on Blazor edit form

I am new to Blazor and I'm trying to do an Add and Edit form, I have a FormComponent which is used on an Add and Edit razor page, all good. On this page I have cascading dropdowns, and these work well on the Add page, but on the edit page when I repopulate the data, the first dropdown has the correct data and the correct data is selected but the subsequent dropdown isn't present. My thoughts are that the ValueChanged event isn't being fired, please see the code below

@if (Level1Categories is not null)
  {
     <div class="nhsuk-grid-row mb-2">
        <div class="nhsuk-grid-column-one-third">
          <label class="nhsuk-label">Category:</label>
        </div>
       <div class="nhsuk-grid-column-two-thirds">
        <InputSelect id="category" class="nhsuk-select"                                                 
         ValueChanged="@((int s) => GetCategoriesById(s))" Value="Links.LevelId" 
         ValueExpression="@(() => Links.LevelId)">
          @if (Level1Categories is not null)
           {
             <option value="0">Please Select</option>
               @foreach (var category in Level1Categories)
                {
                  <option value="@category.Id">@category.Description</option>
                }
          </InputSelect>
         </div>
         </div> 
     }
         @if (Categories is not null  && Categories.Count > 0)
           {
             <div class="nhsuk-grid-row mb-2">
               <div class="nhsuk-grid-column-one-third">
                <label class="nhsuk-label">Sub Category:</label>
                </div>
                <div class="nhsuk-grid-column-two-thirds">
                 <InputSelect id="category" class="nhsuk-select" ValueChanged="@((int s) => 
                  GetSpecialtiesById(s))"  Value="Links.CategoryId" 
                  ValueExpression="@(() => Links.CategoryId)">
                 @if (Categories is not null)
                  {
                   <option value="0">Please Select</option>
                     @foreach (var category in Categories)
                     {
                      <option value="@category.Id">@category.Description</option>
                     }
                     }
                    </InputSelect>
                     </div>
                      </div>
                   }

Below is the c# code for both of the ValueChanged events. This all works well and as expected for the add but not the edit

private async Task GetCategoriesById(int val)
    {
        Links.LevelId = val;
        var query = new GetCategoriesByIdQuery()
        {
            CategoryId =  val
        };
        Categories = (List<CategoryModel>)  await _mediator.Send(query);
        
    }



    private async Task GetSpecialtiesById(int val)
    {
        Links.CategoryId = val;
        var query = new GetCategoriesByIdQuery()
        {
            CategoryId =  val
        };
        Specialties = (List<CategoryModel>) await _mediator.Send(query);

    }

   

So basically I want to know how I can get the ValueChanged event to fire when the edit data is populated, I would expect it to fire because the value is changing, but it isn't. Any help would be very much appreciated. Thanks

As (per Enet's comment) there's not enough code to provide a minimum working example. Here's some code from my archive that shows the wiring of a cascading select based on the Continent/Country context. You should be able to model it into your context.

@page "/"
@inject HttpClient httpClient;

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

<EditForm Model=this.model>
    <div class="row my-2">
        <div class="col text-end">
            <button class="btn btn-danger" @onclick=this.Reset>Reset Record to Empty</button>
        </div>
    </div>
    <div class="row my-2">
        <div class="col">
            <div class="form-label">Continent:</div>
            <InputSelect class="form-select" Value=this.model.Continent ValueExpression="() => this.model.Continent" @oninput=this.OnContininentChange>
                <option value="" selected>-- Select a Continent --</option>
                @foreach (var continent in this.continents)
                {
                    <option value="@continent">@continent</option>
                }
            </InputSelect>
        </div>
    </div>
    <div class="row my-2">
        <div class="col">
            <div class="form-label">Country:</div>
            <InputSelect disabled="@this.isNoContinent" class="form-select" @bind-Value=this.model.Country placeholder="Select a value">
                <option value="" selected>-- Select a Country --</option>
                @foreach (var country in this.countries)
                {
                    <option value="@country.Country">@country.Country</option>
                }
            </InputSelect>
        </div>
    </div>
    <div class="row my-2">
        <div class="col">
            <div class="alert alert-primary mt-3">
                Continent: @this.model.Continent - Country : @this.model.Country
            </div>
        </div>
    </div>
</EditForm>

@code {
    private List<CountryData> dataSet = new List<CountryData>();
    private List<CountryData> countries = new List<CountryData>();
    private List<string> continents = new List<string>();

    private CountryData model = new CountryData { Country = "France", Continent = "Europe" };
    private bool isNoContinent => this.model.Continent == string.Empty;

    protected async override Task OnInitializedAsync()
    {
        await this.GetDataSet();
        await this.GetContinentDataSet();
        await this.GetCountryDataSet();
    }

    private void Reset()
    {
        this.model.Continent = string.Empty;
        this.model.Country = string.Empty;
    }

    private async Task OnContininentChange(ChangeEventArgs e)
    {
        string value = e.Value?.ToString() ?? string.Empty;
        if (value.Equals(model.Continent))
        {
            this.model.Continent = value;
            this.model.Country = string.Empty;
            await this.GetCountryDataSet();
        }
    }

    private async Task GetDataSet()
    {
        // source country file is https://github.com/samayo/country-json/blob/master/src/country-by-continent.json
        // on my site it's in wwwroot/sample-data/countries.json
        this.dataSet = await httpClient.GetFromJsonAsync<List<CountryData>>("sample-data/countries.json") ?? new List<CountryData>();
    }

    private async Task GetCountryDataSet()
    {
        // This would normally call an async data pipeline method
        await Task.Delay(1);
        countries = this.dataSet.Where(item => item.Continent == model.Continent).ToList();
    }

    private async Task GetContinentDataSet()
    {
        // This would normally call an async data pipeline method
        await Task.Delay(1);
        this.continents = this.dataSet.Select(item => item.Continent).Distinct().ToList();
    }

    public class CountryData
    {
        public string Country { get; set; } = string.Empty;
        public string Continent { get; set; } = string.Empty;
    }

}

It looks like this: 在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM