【问题标题】:How do you append a select with a asp-item tag helper如何使用 asp-item 标签助手附加选择
【发布时间】: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 代码示例吗?
  • 我创建了一个演示供您参考。如果您有任何问题,请随时更新我。

标签: javascript jquery asp.net asp.net-core razor


【解决方案1】:

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

  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> Drivers{get;set;}
        public int Index {get;set;}
    }
    
  2. 将 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>
    
  3. 最后,更改您的 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); }
        });
    });
    

[编辑]

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

    <partial name="/Pages/TestingPages/_SecondPage.cshtml" model="@Model.DropdownListViewModel" />
    
  2. 您正在引用一个没有ajax 的苗条jQuery。请将script 更改为&lt;script src="https://code.jquery.com/jquery-3.3.1.min.js"&gt;&lt;/script&gt;

  3. 在创建此元素之前,您正在为#AddButton 绑定一个事件。您需要将 js 包装成 $(document).ready(function(){ .... }。您还可以在#AddButton 元素之后手动创建script。或者,如果您使用默认的Layout,则将&lt;script&gt; 放入@section Scripts{},这将使脚本在页面加载后生效。
  4. 另外,您没有初始化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 的新实例,仍然没有运气:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-16
  • 1970-01-01
  • 2020-07-29
  • 2019-07-27
  • 2019-05-22
相关资源
最近更新 更多