【问题标题】:How to create a cascading SelectList in ASP.Net Core MVC如何在 ASP.Net Core MVC 中创建级联 SelectList
【发布时间】:2017-10-25 21:13:13
【问题描述】:

我曾在具有相同模型值的不同应用程序中使用此功能,但这次我遇到了问题。

我想要实现的是,当我在SelectList 中选择一个值时,另一个值中的值会发生变化。这目前不起作用。

假设我有以下模型:

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");

我认为,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>
    ....

有没有办法让它在第一个 SelectList 中的值是 Monthly 时,显示 MonthList 的值,反之亦然,这样当第一个框改变时,第二个框也会改变?

我能够在我的其他应用程序之一中解决此问题,但它非常麻烦,并且依赖于两个 SelectList 访问相同的模型属性。我想必须有更好的方法来做到这一点。

【问题讨论】:

  • @mjwills 我想解决这个客户端。这是我不想拥有的行为。
  • @AryanFirouzyan 我不确定这对我解决这个问题有何帮助。
  • 抱歉问题不清楚(这是客户端问题)。忽略它。

标签: javascript c# asp.net-core


【解决方案1】:

这应该很容易通过 javascript 来完成。我的方法将使用 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();
        }
    }
});

【讨论】:

  • 我包括 JQuery。谢谢,克里斯。我会检查并更新。
  • 嘿,克里斯,我在代码中换了它,但我注意到您使用的是年份而不是季度。年度需要同时出现在每月和每季度的选择中。这个 sn-p 也不起作用。两个框都出现了,更改时没有任何反应。我的 Bower 包中包含了 JQuery 3.2.1。
  • 可能是我的问题,正在调查。
  • 关于显示的两个框,您可以将一段 javascript 添加到 sn-p 的文档就绪部分,这将隐藏这些框,或者您可以在 HTML 中进行设置使用style="display: none;",这将强制两个框不显示,直到 on change 功能显示其中之一。
【解决方案2】:

执行此操作并不复杂。您所做的就是,首先呈现第一个下拉列表并监听其更改事件并读取该值并使用选定值向服务器进行 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;}    
}

在您的 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);
}

在您看来,使用 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>

使用 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));
                    });
            });
    });

});

这期望您有一个操作方法,该方法接受第一个下拉列表的选定选项值并返回第二个所需的选项。

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);
}

需要注意的重要一点是,在 asp.net 核心中,返回的 JSON 是驼峰式的。所以对于每个选择选项,它是textvalue 而不是TextValue

【讨论】:

  • 感谢详细的回复!我明天去看看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-04
  • 1970-01-01
  • 2021-03-04
  • 2016-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多