如何使用 asp-item 标签助手附加选择

Posted

技术标签:

【中文标题】如何使用 asp-item 标签助手附加选择【英文标题】:How do you append a select with a asp-item tag helper 【发布时间】:2020-02-20 06:03:58 【问题描述】:

我有一个功能,当使用 jQuery 单击按钮时,我会附加一个选择 html。我已经有一个选择,它使用一个 asp-item 标记助手来用我的相应模型填充它。我正在使用的平台是 asp-net core 2.2,我正在为我的页面使用剃须刀页面。

我的问题是如何编辑我的 jQuery,以便当我单击按钮时,asp-item 已经加载到选择中?

这是我的 jQuery 代码:

$("#AddButton").click(function () 
    tc = tc + 1;
    $("#totalContacts").val(tc)
    $(".addselection").append('<div> <select class="form-control" name="[' + (tc) + '].DriverID" asp-for="TripDrivers.DriverID" asp-items="Model.DriverList" > <option value = ""> Select a driver </option></select></div>')
 );

这是我的 OnGet 加载项目

public IActionResult OnGet()


    DriverList = _context.Drivers.Select(a =>
                              new SelectListItem
                              
                                  Value = a.ID.ToString(),
                                  Text = a.FullName
                              ).ToList();
                             

这是我的第一个问题,如果有任何语法错误或信息缺失,请多多包涵。如有需要,我会添加它们。

编辑:Here is the design I'm trying to do.

单击加号按钮后。它应该添加一行下拉列表,每个下拉列表中的选项都是从 OnGet 方法的列表中加载的。

另一个编辑:根据用户@itminus 的说明,我创建了一个示例页面和一个部分视图来应用下面给出的代码。

这是我的 FirstPage.cshtml 的样子

@page
@model MasigasigTrackingSystem.Pages.TestingPages.FirstPageModel
@
    Layout = null;


<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>FirstPage</title>
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
    <script>
        $("#AddButton").click(function () 
            tc = tc + 1;
            $("#totalContacts").val(tc)
            $.ajax('?handler=DropdownList', 
                method: "GET",
                data:  tc: tc ,
                success: function (d)  $(".addselection").append(d); 
            );
        );
    </script>

</head>
<body>
    <button id="AddButton" class="btn" type="button">+</button>
    @*<select asp-for="Mode" asp-items="Model.DropdownListViewModel.Drivers" class="form-control">
        <option value="">Select a driver</option>
    </select>*@
    <div class="addselection">
        <partial name="_SecondPage.cshtml" />
    </div>
</body>
</html>

我的FirstPageModel

namespace MasigasigTrackingSystem.Pages.TestingPages

    public class FirstPageModel : PageModel
    
        private readonly MasigasigTrackingSystem.Data.ApplicationDBContext _context;

        public FirstPageModel(MasigasigTrackingSystem.Data.ApplicationDBContext context)
        
            _context = context;
        

        [BindProperty]
        public Drivers Drivers  get; set; 

        public List<SelectListItem> DriverList  get; set; 

        [BindProperty]
        public DropdownListViewModel DropdownListViewModel  get; set; 

        public void OnGet()
        
            DriverList = _context.Drivers.Select(a =>
                              new SelectListItem
                              
                                  Value = a.ID.ToString(),
                                  Text = a.FullName
                              ).ToList();

            DropdownListViewModel = new DropdownListViewModel();

            DropdownListViewModel.Drivers = DriverList;
        

        public IActionResult OnGetDropdownListAsync(int tc)
        
            var list = _context.Drivers.Select(a => new SelectListItem
            
                Value = a.ID.ToString(),
                Text = a.FullName,
            ).ToList();  // or filter by Where( ... tc...).ToList()
            return Partial("/Pages/TestingPages/_SecondPage.cshtml", new DropdownListViewModel
            
                Drivers = list,
                ID = tc,
            );
        
    

我的部分_SecondPage

@using MasigasigTrackingSystem.Models
@model DropdownListViewModel

<div>
    <select class="form-control dropdown" name="[@Model.ID].DriverID" asp-items="@Model.Drivers">
        <option> Select a driver </option>
    </select>
</div>

我的DropdownlistViewModel

namespace MasigasigTrackingSystem.Models

    public class DropdownListViewModel
    
        public int ID  get; set; 
        public IList<SelectListItem> Drivers  get; set; 
    

【问题讨论】:

只是好奇:为什么不在浏览器中加载页面之前在服务器上渲染&lt;select&gt; @itminus 有可能吗?我正在尝试做的有点像动态表单,我可以根据用户需要输入的项目数量添加或删除下拉列表。 您的原始代码将不起作用,因为 &lt;select asp-for ... asp-items&gt; 只能在服务器端呈现。我不确定你想做什么。但我认为如果您想动态渲染select,可以使用ajax 并返回select 部分视图。 嗨@itminus。我已经编辑了上面的问题,看看它是否有助于让您了解我想要完成的工作。如果你的答案还是和以前一样。我可以要求提供可以为我指明正确方向的 ajax 代码示例吗? 我创建了一个演示供您参考。如果您有任何问题,请随时更新我。 【参考方案1】:

这是一个从服务器动态获取局部视图的演示。

    在您的 PageModel 中创建一个处理程序 OnGetDropdownListAsync(int tc)

    public class YourPageModel : PageModel
    
        ... other handler methods, e.g. OnGet() render the Index
    
        public IActionResult OnGetDropdownListAsync(int tc)
        
            var list = _context.Drivers.Select(a =>new SelectListItem
                Value = a.ID.ToString(),
                Text = a.FullName,
            ).ToList();  // or filter by Where( ... tc...).ToList()
            return Partial( "/Pages/Shared/Selection.cshtml" , new DropdownListViewModel
                Drivers = list,
                Index = tc,
            );
        
    
    

    这里的DropdownListViewModel 是一个保存数据的普通ViewModel

    public class DropdownListViewModel
        public IList<SelectListItem> Driversget;set;
        public int Index get;set;
    
    

    将 jQuery 中的原始 html sn-p 移动到新的局部视图文件中:/Pages/Shared/Selection.cshtml

    @using App.Pages
    @model DropdownListViewModel
    
    <div> 
        <select class="form-control dropdown" name="[@Model.Index].DriverID" asp-items="@Model.Drivers">
            <option> Select a driver </option>
        </select>
    </div>
    

    最后,更改您的 javascript 以发送 ajax 请求并按以下方式更新 UI:

    $("#AddButton").click(function () 
        tc = tc + 1;
        $("#totalContacts").val(tc)
        $.ajax('?handler=DropdownList',
            method:"GET",
            data: tc: tc ,
            success:function(d) $(".addselection").append(d); 
        );
    );
    

[编辑]

    您将正确的 ViewData 隐式传递给 &lt;partial&gt;,这会导致此类型错误。您需要将其更改为:

    <partial name="/Pages/TestingPages/_SecondPage.cshtml" model="@Model.DropdownListViewModel" />
    

    您正在引用一个没有ajax 的苗条jQuery。请将script 更改为&lt;script src="https://code.jquery.com/jquery-3.3.1.min.js"&gt;&lt;/script&gt;

    在创建此元素之前,您正在为#AddButton 绑定一个事件。您需要将 js 包装成 $(document).ready(function() .... 。您还可以在#AddButton 元素之后手动创建script。或者,如果您使用默认的Layout,则将&lt;script&gt; 放入@section Scripts,这将使脚本在页面加载后生效。 另外,您没有初始化tc 变量。

简而言之,您需要修复以下错误:

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
    $(document).ready(function()
        var tc = 0;
        $("#AddButton").click(function () 
            tc = tc + 1;
            $("#totalContacts").val(tc)
            $.ajax('?handler=DropdownList', 
                method: "GET",
                data:  tc: tc ,
                success: function (d)  $(".addselection").append(d); 
            );
        );
    );
</script>

...

<div class="addselection">
    <partial name="/Pages/TestingPages/_SecondPage.cshtml" model="@Model.DropdownListViewModel" />
</div

【讨论】:

由于某种原因,我似乎无法在部分视图中加载数据。我需要在我的初始页面中加载它吗?我尝试使用一个空白页和一个局部视图来测试它。似乎无法让它工作。 @trymode 1. 是的。部分视图应在初始页面中由 ajax 加载。 2. 实际上,我测试了我的代码,我可以确保它对我来说可以正常工作。如果您做不到,能否请您向我们展示完整的代码或重现相同问题的项目/方法? 抱歉回复晚了,但我做了一些测试,现在收到一条错误消息 InvalidOperationException:传递到 ViewDataDictionary 的模型项的类型为“MasigasigTrackingSystem.Pages.TestingPages.FirstPageModel” ,但此 ViewDataDictionary 实例需要“MasigasigTrackingSystem.Models.DropdownListViewModel”类型的模型项。我再次编辑了我的问题,以发布包含您的代码的页面。 @trymode 将我的回复作为一条评论发布太长了。请查看我的更新答案以了解如何解决该问题:) 我想我已经到了终点线。我仍然收到相同的错误消息,但这次它指向 OnGetDropdownListAsync 函数中的返回 Partial,错误消息与之前相反,它现在试图从 FirstPage 中要求 DropdownListViewModel。我已经尝试从部分页面中删除模型标签,我什至删除了 DropdownListViewModel 的新实例,仍然没有运气:(

以上是关于如何使用 asp-item 标签助手附加选择的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET CORE MVC 选择标签助手 - 如何在不使用 ModelView 的情况下设置选定值

如何在循环中设置 asp-items 和 asp-for

如何在 Blazor 中使用 TagHelpers?

如何在 xcode 自动布局中使对象自动调整大小?

如何使工具栏附加到底部 iOS Swift

如何使这种自​​动布局安排与滚动视图一起使用