简体   繁体   English

如何在ASP.Net Core MVC中创建级联SelectList

[英]How to create a cascading SelectList in ASP.Net Core MVC

I had this working in a different application with the same model values, but I've run into a problem this time around. 我曾在具有相同模型值的不同应用程序中工作,但是这次我遇到了一个问题。

What I want to achieve is that when I select one value in one SelectList , the values in a different one are changed. 我要实现的是,当我在一个SelectList选择一个值时,在另一个中的值将被更改。 This is not currently working. 目前无法使用。

Say I have the following model: 说我有以下模型:

public class DashboardChartsByMonthModel
{
    ...
    public SelectList TimeSliceList { get; set; }
    public TimeSlice TimeSliceVal { get; set; } // Timeslice is an Enum containing "ByMonth" and "ByQuarter"
    public SelectList StartQuarterList { get; set; }
    public string StartQuarter { get; set; }
    public SelectList StartMonthList { get; set; }
    public string StartMonth { get; set; }
    public SelectList StartYearList { get; set; }
    public string StartYear { get; set; }
    ....
    public void SetDefaults()
    {
        ...
        TimeSliceList = new SelectList(new List<SelectListItem>
        {
            new SelectListItem {Selected = true, Text = "Monthly", Value = TimeSlice.ByMonth.ToString()},
            new SelectListItem {Selected = false, Text = "Quarterly", Value = TimeSlice.ByQuarter.ToString()}
        }, "Value", "Text");
}
        StartQuarterList = new SelectList(new List<SelectListItem>
        {
            new SelectListItem {Selected = true, Text = "Q1", Value = "1"},
            new SelectListItem {Selected = false, Text = "Q2", Value = "4"},
            new SelectListItem {Selected = false, Text = "Q3", Value = "7"},
            new SelectListItem {Selected = false, Text = "Q4", Value = "10"}
        }, "Value", "Text");

        StartMonthList = new SelectList(new List<SelectListItem>
        {
            new SelectListItem {Selected = true, Text = "January", Value = "1"},
            new SelectListItem {Selected = false, Text = "February", Value = "2"},
            new SelectListItem {Selected = false, Text = "March", Value = "3"},
            new SelectListItem {Selected = false, Text = "April", Value = "4"},
            new SelectListItem {Selected = false, Text = "May", Value = "5"},
            new SelectListItem {Selected = false, Text = "June", Value = "6"},
            new SelectListItem {Selected = false, Text = "July", Value = "7"},
            new SelectListItem {Selected = false, Text = "August", Value = "8"},
            new SelectListItem {Selected = false, Text = "September", Value = "9"},
            new SelectListItem {Selected = false, Text = "October", Value = "10"},
            new SelectListItem {Selected = false, Text = "November", Value = "11"},
            new SelectListItem {Selected = false, Text = "December", Value = "12"}
        }, "Value", "Text");

        StartYearList = new SelectList(new List<SelectListItem>
        {
            new SelectListItem {Selected = false, Text = "2016", Value = "2016"},
            new SelectListItem {Selected = true, Text = "2017", Value = "2017"}
        }, "Value", "Text");

And my view, a Razor(.cshtml) page, has the following: 我的视图是Razor(.cshtml)页面,具有以下内容:

<body>
    ....
    <form method="post">
            <h3>By Month or Quarter</h3>
            <select id="TimeSlice" name="TimeSlice" asp-for="TimeSliceVal" asp-items="@Model.TimeSliceList"></select>
            Start:<select id="StartMonth" name="StartMonth" asp-for="StartMonth" asp-items="@Model.StartMonthList"></select>
            <select id="StartYear" name="StartYear" asp-for="StartYear" asp-items="@Model.StartYearList"></select>
    ....

is there a way to have it so that if the value in the first SelectList is Monthly, it displays the values of the MonthList and vice versa so that when the first box is changed, the second box changes as well? 有没有一种方法可以使第一个SelectList中的值是Monthly,则显示MonthList的值,反之亦然,以便当第一个框更改时,第二个框也更改?

I was able to solve this problem in one of my other applications but it was very cumbersome and relied on both of the SelectLists accessing the same model property. 我能够在我的其他应用程序中解决此问题,但它非常麻烦,并且依赖于两个SelectList访问相同模型属性。 I imagine there has to be a better way to do this. 我认为必须有一种更好的方法来做到这一点。

This should be pretty simple to do via javascript. 通过javascript做到这一点应该很简单。 My approach will use JQuery, if you aren't using JQuery there are resources available to help you convert it into native javascript code. 我的方法将使用JQuery,如果您不使用JQuery,则有可用的资源可帮助您将其转换为本地javascript代码。

$(document).ready(function() {
    $("#TimeSlice").on("change", function() {
        var selectedValue = $(this).val();
        if(val === "Whatever the value of Monthly is here")
        {
            $("#StartMonth").show();
            $("#StartYear").hide();
        }
        else if(val === "Whatever the value of Quarterly is here"){     
            $("#StartYear").show();
            $("#StartMonth").hide();
        }else{
            //If you have any other options in the dropdown, such as a default value or placeholder, this will hide both quarterly and monthly
            $("#StartYear").hide();
            $("#StartMonth").hide();
        }
    }
});

There is nothing complicated to do this. 这样做并不复杂。 All you do is, first render the first dropdown and listen to the change event of that and read the value and make an ajax call with selected value to the server where it will return the appropriate list of SelectListItems to render the second dropdown. 您要做的就是,首先呈现第一个下拉列表,并听其更改事件并读取该值,并向服务器发出带有选定值的ajax调用,服务器将在其中返回SelectListItems的适当列表以呈现第二个下拉列表。

public class DashboardChartsByMonthModel
{
   public List<SelectListItem> TimeSliceList { set;get;}
   public int SelectedTimeSlice { set;get;}

   public List<SelectListItem> TimeOptions{ set;get;}
   public int SelectedTimeOption { set;get;}    
}

in your GET action, you load the first dropdown data 在GET操作中,加载第一个下拉数据

public IActionResult Create()
{
  var vm= new DashboardChartsByMonthModel();
  vm.TimeSliceList = new List<SelectListItem>
  {
        new SelectListItem {Selected = true, Text = "Monthly",
                                             Value = TimeSlice.ByMonth.ToString()},
        new SelectListItem {Selected = false, Text = "Quarterly",
                                              Value = TimeSlice.ByQuarter.ToString()}
  };
  return View(vm);
}

and in your view, use the SELECT tag helper 在您看来,请使用SELECT标签帮助器

@model DashboardChartsByMonthModel
<form asp-action="Create" asp-controller="Home" method="post">    
    <select asp-for="SelectedTimeSlice" asp-items="@Model.TimeSliceList"></select>
    <select id="SelectedTimeOption" name="SelectedTimeOption" 
                                    data-url="@Url.Action("GetTimes")"></select>
    <input type="submit" />
</form>

The javascript to handle change event is pretty simple with jQuery 使用jQuery处理变更事件的JavaScript非常简单

$(function () {

    $("#SelectedTimeSlice").change(function() {
        var v = $(this).val();
        var url = $("#SelectedTimeOption").data("url") + '?value=' + v;
        $.getJSON(url,function(data) {
                $("#SelectedTimeOption").empty();
                $.each(data,
                    function(i, item) {
                        $("#SelectedTimeOption")
                     .append($("<option>").text(item.text).val(item.value));
                    });
            });
    });

});

This expects you have an action method which accepts the selected option value of first dropdown and return the options needed for second. 期望您有一个操作方法,该方法接受选择的第一个下拉菜单的选项值并返回第二个所需的选项。

public IActionResult GetTimes(string value)
{
    if (value == TimeSlice.ByMonth.ToString())
    {
        var l = new List<SelectListItem>
        {
            new SelectListItem {Selected = true, Text = "January", Value = "1"},
            new SelectListItem {Selected = false, Text = "February", Value = "2"}
        };
        return Json(l);
    }
    var t2 = new List<SelectListItem>
    {
        new SelectListItem {Selected = true, Text = "Q1", Value = "1"},
        new SelectListItem {Selected = false, Text = "Q2", Value = "2"}
    };
    return Json(t2);
}

The important to thing to notice is, In asp.net core the returned JSON is camel case. 需要注意的重要一点是,在asp.net核心中,返回的JSON是驼峰式大小写。 So for each select option, it is text and value instead of Text and Value 因此,对于每个选择选项,它都是textvalue而不是TextValue

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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