简体   繁体   中英

Model properties not bind to dropdowns in Blazor

I have 2 cascade dropdowns:

在此处输入图像描述

The problem is when I click on Save button my model would be empty. I can't use bind-value in my dropdowns because I can't use onchange event. How can I have cascade feature as long as binding properties.

Codes:

@using Model

<select value="@MyLocation.CountryCode" @onchange="@CountryChanged">
@if (string.IsNullOrEmpty(MyLocation.CountryCode) == true)
{
     <option value="0" selected>[Choose One...]</option>
}

@foreach (var item in Countries)
{
     <option value="@item.Key">@item.Value</option>
}
</select>
<br />
<select value="@MyLocation.CityCode">
@foreach (var item in CountryCities)
{
     <option value="@item.Key">@item.Value</option>
}
</select>
<br />
<button class="btn btn-success" @onclick="() => HandleSave()">Save</button>

@code {

public Location MyLocation { get; set; } = new Location();
private Dictionary<string, string> Countries { set; get; } = new Dictionary<string, string>();
private Dictionary<string, string> CountryCities { set; get; } = new Dictionary<string, string>();

protected override Task OnInitializedAsync()
{
    Countries.Add("01", "Germany");
    Countries.Add("02", "Japan");
    Countries.Add("03", "England");

    return base.OnInitializedAsync();
}

private async Task CountryChanged(ChangeEventArgs e)
{
    CountryCities.Clear();
    switch (e.Value.ToString())
    {
        case "01":
            CountryCities.Add("001", "Munchen");
            break;
        case "02":
            CountryCities.Add("002", "Tokyo");
            break;
        case "03":
            CountryCities.Add("003", "Manchester");
            break;
    }
}

private void HandleSave()
{
    var Country = MyLocation.CountryCode; <--- CountryCode is null
}
}

On the CountryChanged method you can add:

MyLocation.CountryCode = e.Value.ToString();

You can do the same for the CityCode:

<select value="@MyLocation.CityCode" @onchange="@OnCityChanged">
@foreach (var item in CountryCities)
{
    <option value="@item.Key">@item.Value</option>
}

@code {
private void OnCityChanged(ChangeEventArgs e) => MyLocation.CityCode = e.Value.ToString();
}

Edit: Note that for the OnCityChanged to work, user have to actually select a value. In case that they don't, the first value (in your case Muchen, Tokyo, Manchester) won't be set as property in your model. For that scenario, you can do something like that, in the CountryChanged method:

switch (e.Value.ToString())
    {
        case "01":
            CountryCities.Add("001", "Munchen");
            MyLocation.CityCode= "001";
            ...
@page "/"

<select class="form-control" value="@MyLocation.CountryCode"
        @onchange="@((args) => { MyLocation.CountryCode = args.Value.ToString(); SelectCities(args); })">

    <option value="">Select Country...</option>
    @foreach (var country in countryList)
    {
        <option value="@country.Code"> @country.Name </option>
    }
 
</select>
<br />
@if (cityList != null && cityList.Any())
{
    <select class="form-control" @bind="@MyLocation.CityCode">
       @foreach (var city in cityList)
       {
               <option value="@city.Code">@city.Name</option>
       }
    </select>
}
    <br />

    <button class="btn btn-success" @onclick="() => HandleSave()">Save</button>

    @code {

        private Location MyLocation = new Location();


        private IList<Country> countryList = new List<Country>
  {
            new Country
            {
                Code = "001", Name="USA",
                Cities = new List<City> {  new City { Code = "1", Name = "City1" },
                         new City { Code = "2", Name = "City2" } }
            },
            new Country
            {
                Code = "002", Name="Germany",
                Cities = new List<City> {  new City { Code = "3", Name = "City1" },
                         new City { Code = "4", Name = "City2" } }
            },
            new Country
            {
                Code = "003", Name="France",
                Cities = new List<City> {  new City { Code = "5", Name = "City1" },
                         new City { Code = "6", Name = "City2" } }
            },

            new Country
            {
                Code = "004", Name="UK",
                Cities = new List<City> {  new City { Code = "7", Name = "City1" },
                         new City { Code = "8", Name = "City2" },
                         new City { Code = "9", Name = "City3" },
                         new City { Code = "10", Name = "City4" }}
            },

            new Country { Code = "005", Name="Russia",
               Cities =  new List<City>  {  new City { Code = "11", Name = "City1" } }}
        };


        private IQueryable<City> cityList;

        private void HandleSave()
        {
            Console.WriteLine($"MyLocation.CountryCode: {MyLocation.CountryCode}");
            Console.WriteLine($"MyLocation.CityCode: {MyLocation.CityCode}");
         
        }

        private void SelectCities(ChangeEventArgs args)
        {
            // Note: Each time SelectCities is called MyLocation.CityCode should be set to null.
            MyLocation.CityCode = null;
            string countryCode = args.Value.ToString();

            cityList = (from country in countryList
                        where country.Code == countryCode
                        from city in country.Cities
                        select city).AsQueryable();
        }

        public class Location
        {
            public string CountryCode { get; set; }
            public string CityCode { get; set; }

        }

        public class Country
        {
            public string Code { get; set; }
            public string Name { get; set; }

            public IList<City> Cities { get; set; }
        }

        public class City
        {
            public string Code { get; set; }
            public string Name { get; set; }

        }

    }

Now try to convert this code to work with the Forms' InputSelect component, embedded within an EditForm

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