首页 > 解决方案 > 在 .net-core 中选择 onchange 到 Controller 的 Action

问题描述

我有一个按类型分类的对象列表,所以我的视图上有一个“类型”选择

<form asp-action="Index" asp-route-type=" ? selectedTypeId ? ">
    <select asp-items="ViewBag.Types" onchange="this.form.submit()"></select>
</form>

我的控制器的动作是

public async Task<IActionResult> Index([FromQuery(Name = "type")] int type) {
   // filter the object list by type 
}

如何使用选择正确重新加载视图?

我看到提出了 Ajax 解决方案,这将是一个很好的解决方案,但是我的问题是,当我更改产品类型时,不仅产品列表会更改,而且产品特性(列)也会更改,创建按钮也应该只创建产品类型,因此,它会改变所有视图行为。我宁愿重新加载所有视图而不是其中的一部分。

标签: .netasp.net-core.net-5asp.net-core-tag-helpersasp.net-core-5.0

解决方案


如何使用选择正确地重新加载视图?

看来您想根据 DropDownList 选择的值过滤数据,在我看来,我更喜欢使用 Partial View 来显示过滤后的数据并使用 JQuery Ajax 来更新内容。请参考以下示例:

创建一个 ProductViewModel 视图模型:

public class ProductViewModel
{
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public string ProductType { get; set; }
}

控制器方法:

    //ProductIndex Page
    public IActionResult ProductIndex()
    {
        //get all the initial data from the repository
        var productlist = _repo.GetProductViewModels();

        //set select items for the DropDownList
        ViewBag.Types = _repo.GetProductViewModels().Select(c=>c.ProductType).Distinct().ToList().Select(c => new SelectListItem { Text = c, Value = c }).ToList();
        return View(productlist);
    }

    //based on the type filter data and return partial view.
    public IActionResult ShowProduct(string type)
    {
        var productlist = _repo.GetProductViewModels().ToList();

        //based on the type to filter data.
        if (!string.IsNullOrEmpty(type) && type != "all")
        {
            productlist = productlist.Where(c => c.ProductType == type).ToList();
        }

        //required using Microsoft.AspNetCore.Mvc.Rendering;
        ViewBag.Types = _repo.GetProductViewModels().Select(c => new SelectListItem { Text = c.ProductType, Value = c.ProductType }).Distinct().ToList();
        return PartialView("_ShowProductPartialView", productlist );
    }

创建_ShowProductPartialView.cshtml局部视图以显示产品列表:

@model IEnumerable<netcore5.Models.ProductViewModel>
 
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.ProductId)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.ProductName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.ProductType)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.ProductId)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.ProductName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.ProductType)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
            </td>
        </tr>
}
    </tbody>
</table>

ProductIndex 页面中的代码:

@model IEnumerable<netcore5.Models.ProductViewModel>

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

<h1>ProductIndex</h1>
 
<form asp-action="ProductIndex">
    <select id="ddltype" name="type" asp-items="ViewBag.Types" >
        <option value="all">All Type</option>
    </select>
    <div id="productcontainer"> 
        <partial name="_ShowProductPartialView.cshtml" model="@Model" />
    </div> 
</form>


@section Scripts{ 
<script>  
    $(function () {
        $("#ddltype").change(function () {
            $.ajax({
                type: "Get",
                url: "/Home/ShowProduct?type=" + $(this).val(),  //remember change the controller to your owns.  
                success: function (data) {
                    $("#productcontainer").html("");
                    $("#productcontainer").html(data);
                },
                error: function (response) {
                    console.log(response.responseText);
                }
            });
        });
    });
</script>
}

然后,结果如下:

在此处输入图像描述

【注意】使用上述方法,主页面不会更新,只刷新局部视图。

如果你想使用<select>元素onchange事件,你可以Submit在表单中添加一个按钮,在onchange事件中,点击Submit按钮,它会提交表单。然后,您可以根据类型过滤数据。

将上面的代码更改如下: 在 ProductIndex.cshtml 页面中,删除 JQuery 脚本并添加一个提交按钮,为select元素添加名称属性,然后在 selectonchange事件中,单击提交按钮:

@model IEnumerable<netcore5.Models.ProductViewModel>

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

<h1>ProductIndex</h1>
 
<form asp-action="ProductIndex">
    <select id="ddltype" name="type" asp-items="ViewBag.Types" onchange="document.getElementById('btnSubmit').click();" >
        <option value="all">All Type</option>
    </select>
    <div id="productcontainer"> 
        <partial name="_ShowProductPartialView.cshtml" model="@Model" />
    </div>

    <input id="btnSubmit" hidden type="submit" value="submit" />
</form>

控制器中的代码:

    public IActionResult ProductIndex(string type)
    {
        //get all the initial data from the repository
        var productlist = _repo.GetProductViewModels();

        //based on the type to filter data.
        if (!string.IsNullOrEmpty(type) && type != "all")
        {
            productlist = productlist.Where(c => c.ProductType == type).ToList();
        }

        //set select items for the DropDownList
        ViewBag.Types = _repo.GetProductViewModels().Select(c=>c.ProductType).Distinct().ToList().Select(c => new SelectListItem { Text = c, Value = c }).ToList();
        return View(productlist);
    }

结果是这样的:

在此处输入图像描述

如我们所见,主页面将刷新。所以,我更喜欢使用 JQuery Ajax 来加载局部视图。


推荐阅读