Make dropdown list dependent on another dropdown in ASP.NET Core MVC without JS

Viewed 1152

I have to do dropdown list with names of plates and due to selected name show all subtypes of that plate. This looks like this in code:

Country Class:

public class Country
{
    public List<Plate> plates { get; set; }
    public string name { get; set; }

    public Country(string jsonRead)
    {
        plates = JsonConvert.DeserializeObject<List<Plate>>(jsonRead);
    }

    public IEnumerable<Plate> getAllPlates()
    {
        return plates.OrderBy(r => r.type);
    }
}

Plate class:

public class Plate
{
    public string type { get; set; }
    public List<Subtype> subtypes { get; set; }

    public Plate()
    {
        subtypes = new List<Subtype>();
    }
}

Subtype class:

public class Subtype
{
    public string subtypeName { get; set; }
    public string color { get; set; }

    public Subtype(string subtype, string color)
    {
        this.subtypeName = subtype;
        this.color = color;
    }
}

In the controller, I have a field CountryData. It has information about all tables (I read it from file) and function to view where I want to have these 2 dropdownlists:

[Route("Home/CreatePlate/{name}")]
public IActionResult CreatePlate(string name)
{
    var model = countryData.GetCountry(name);
    return View(model);
}

And finally CreatePlate.cshtml view:

@model Generator.Country

@{
    ViewData["Title"] = "CreatePlate";
}

<h1>CreatePlate</h1>

<div>
    <h4>Country</h4>
    <hr />
    <dl class="row">
        <dt class="col-sm-2">

            <select id="Plate" name="Plate" onchange="this.form.submit()">
                @if (Model.plates != null)
                {
                    foreach (var Title in Model.plates)
                    {
                        <option value="@Title.type">@Title.type</option>
                    }
                }
            </select>

            <select id="Subtype" name="Subtype" onchange="this.form.submit()">
                @if (Model.plates != null)
                {
                    foreach (var Title in Model.plates.Select(r => r))
                    {
                        foreach (var subtype in Title.subtypes) 
                        {
                        <option value="@subtype.subtypeName">@subtype.subtypeName</option>
                        }
                    }
                }
            </select>

        </dt>
        <dd class = "col-sm-10">
        </dd>
    </dl>
</div>

For now I show all plates in first foreach, but in the second, I get ALL subtypes instead of that selected in first dropdownlist.

I saw a few solutions on Stackoverflow, but all of them need JS (I don't know that lang) and also are little different from my problem.

That's my 1st project in ASP.NET Core MVC.

2 Answers

The simple answer is 'No'. You can't do that without using JS. If you are doing web development. JS is pretty much a basic requirement!

So the solution... Learn JS. You know C#. The syntax is the same. Or find JS that almost does the job (it is available) and modify it.

It is impossible to avoid using JS. If you do not want to learn JS, at least using this.form.submit().

Here is a whole working demo:

Model:

public class Plate
{
    public string type { get; set; }
    public List<Subtype> subtypes { get; set; }
    public Plate()
    {
        subtypes = new List<Subtype>();
    }
}
public class Subtype
{
    public string subtypeName { get; set; }
    public string color { get; set; }
    public Subtype(string subtype, string color)
    {
        this.subtypeName = subtype;
        this.color = color;
    }
}
public class Country
{
    public List<Plate> plates { get; set; }
    public string name { get; set; }     
}

View:

@model Country    
@{
    ViewData["Title"] = "CreatePlate";
}    
<h1>CreatePlate</h1>
<form>
    <div>
        <h4>Country</h4>
        <hr />
        <dl class="row">
            <dt class="col-sm-2"> 
                <select id="Plate" name="Plate" onchange="this.form.submit()">
                    @if (Model.plates != null)
                    {
                        foreach (var Title in Model.plates)
                        {
                            <option value="@Title.type" selected="@(ViewBag.SelectedIndex==Title.type?"selected":null)" >@Title.type</option>
                        }
                    }
                </select>

                <select id="Subtype" name="Subtype">
                    @if (Model.plates != null)
                    {
                        foreach (var Title in Model.plates.Select(r => r))
                        {
                            foreach (var subtype in Title.subtypes)
                            {
                                <option value="@subtype.subtypeName">@subtype.subtypeName</option>
                            }
                        }
                    }
                </select>

            </dt>
            <dd class="col-sm-10">
            </dd>
        </dl>
    </div>

</form>

Controller:

public class HomeController : Controller
{
    //hard coded the data
    List<Country> country = new List<Country>()
    {
        new Country(){
            name="aa",
            plates= new List<Plate>()
            {
                new Plate(){type="p1",subtypes=new List<Subtype>(){new Subtype("sub1","red"),new Subtype("sub2","yellow")}},
                new Plate(){type="p2",subtypes=new List<Subtype>(){new Subtype("sub3","green"),new Subtype("sub4","blue")}},
                new Plate(){type="p3",subtypes=new List<Subtype>(){new Subtype("sub5","gray")}}
            }
        }
    };
      
    [Route("Home/CreatePlate/{name}")]
    public IActionResult CreatePlate(string name, string Plate)   
    {
        ViewBag.SelectedIndex = "p1";
        //get all the data of three tables
        var model = country.Where(a=>a.name==name).FirstOrDefault();
        if (Plate != null)
        {
            model.plates.Where(a => a.type != Plate).Select(a => a.subtypes).ToList().ForEach(a => a.Clear());
            ViewBag.SelectedIndex = Plate;  //used to keep the selected item
            return View(model);
        }

        model.plates.ForEach(a => a.subtypes.Clear());
        return View(model);
    }
}
Related