【问题标题】:A view to add and remove items from a collection on the same view在同一视图上从集合中添加和删除项目的视图
【发布时间】:2016-11-13 08:46:39
【问题描述】:

我正在创建一个视图,允许用户以客户想要的特定方式添加和删除列表中的对象。用户必须能够在提交之前在页面上添加或删除多个表单。当页面发布时,它需要显示列表中已有的内容,并可以选择删除每个项目,并允许用户在再次提交之前添加/删除更多对象。

我可以使用 JQuery 和 Partial View 让用户在提交之前添加或删除新表单。我想不通的是如何提供一个按钮来从以前的提交中删除列表中已经存在的对象。

谁能帮我解决这个问题?将不胜感激。

这是我到目前为止所想出的。 在我看来:

@using (Html.BeginForm())
{
    <div id="recipients">
        @foreach (var p in Model)
        {
            @Html.Partial("_Recipient", p)
        }

        <div id="recipients0"></div>
    </div>
    <button id="add" type="button">Add</button>
    <button id="remove" type="button">Remove</button>
    <input type="submit" value="Save" />
}

<script type="text/javascript">
    $('#add').click(function () {
        var url = '@Url.Action("Recipient")';
        var div = $('#recipients');
        var divlast = $('div[id^="recipients"]:last');

        var num = parseInt(divlast.prop("id").match(/\d+/g), 10) + 1;


        var newdiv = $(document.createElement('div')).attr('id', 'recipients' + num)//rest of code

        $.get(url, function (response) {
            div.append(newdiv);
            newdiv.append(response);
        });
    })
    $('#remove').click(function () {
        var div = $('#recipients');
        var divlast = $('div[id^="recipients"]:last');
        var num = parseInt(divlast.prop("id").match(/\d+/g), 10);
        alert("div[id='recipients" + num + "']");
        $("div[id='recipients" + num + "']").remove();
        //div.remove('div[id^="recipients' + num + '"]');
    })

带有向新对象添加数据的表单的部分视图:

@using (Html.BeginCollectionItem("recipients"))
{
    @Html.HiddenFor(m => m.ID)
    @Html.LabelFor(m => m.Recipient)
    @Html.TextBoxFor(m => m.Recipient)
    @Html.ValidationMessageFor(m => m.Recipient)
    <br />
    @Html.LabelFor(m => m.Amount)
    @Html.TextBoxFor(m => m.Amount)
    @Html.ValidationMessageFor(m => m.Amount)


}
<td>
    @Ajax.ActionLink(
        "Remove",
        "Remove",
        "CashRecipients",

        new AjaxOptions
        {
            HttpMethod = "POST",
            OnSuccess = "onDeleteSuccess"
        }
    )
</td>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>

<script>
    var onDeleteSuccess = function (result) {
        alert('Howdy');
    };
</script>

我的控制器:

    public PartialViewResult Recipient()
    {
        return PartialView("_Recipient", new CashRecipientViewModel());
    }

    // GET: 
    public ActionResult Create()
    {
        List<CashRecipientViewModel> model = new List<CashRecipientViewModel>();

        return View(model);
    }

    // POST: CashRecipients/Create
    [HttpPost]
    public ActionResult Create([Bind(Include = "ID,Amount,Recipient")] IEnumerable<CashRecipientViewModel> recipients)
    {

        return View(recipients);

    }

我的视图模型:

public class CashRecipientViewModel
{
    public int? ID { get; set; }
    public decimal Amount { get; set; }
    [Required(ErrorMessage = "Please enter the name of the recipient")]
    public string Recipient { get; set; }
}

【问题讨论】:

  • 你没有显示部分(我假设你使用BeginCollectionItem())。封闭&lt;div&gt; 元素的id 属性有什么意义(这是不必要的)。我为什么没有与每个元素关联的删除按钮(用户想要删除 10 个列表中的第三个?)
  • 我编辑了问题以添加部分内容。封闭 div 元素的 id 属性用于底部删除按钮的 jquery。包括与每个元素关联的删除按钮正是我要问的。
  • 您可以在此处看到它正在运行:dynamicform.azurewebsites.net/CashRecipients/Create 底部的删除按钮用于在提交表单之前将其删除。部分视图中的删除操作链接当前正在调用一个空方法...我不知道如何从那里获取列表上的范围。
  • 您没有显示部分(带有BeginCollectionItem() 和用于编辑模型的表单控件。而且您没有(也不应该)为这些div 生成id 属性。您partial 需要一个带有类名的按钮,并且您处理按钮单击事件以删除关联的表单控件(在现有项目的情况下,使用 ajax 调用服务器方法将其删除,或“标记”模型以进行删除)跨度>
  • 对不起,遗漏了部分视图代码;编辑添加它。请查看主视图 JQuery 是如何使用这些 id 属性的——这很有意义。使用 ajax 调用服务器方法是部分中的操作链接已经在做的事情。我只是不知道如何通过整个列表。

标签: jquery asp.net-mvc asp.net-mvc-partialview begincollectionitem


【解决方案1】:

只有一个“删除”按钮没有意义,您需要与集合中的每个项目关联一个“删除”。此外,从 &lt;div&gt; 元素中删除 id 属性并使用相对选择器。

将部分更改为

@using (Html.BeginCollectionItem("recipients"))
{
    <div class="item" data-id="@Model.ID"> // add an enclosing element
        @Html.HiddenFor(m => m.ID)
        @Html.LabelFor(m => m.Recipient)
        @Html.TextBoxFor(m => m.Recipient)
        @Html.ValidationMessageFor(m => m.Recipient)
        @Html.LabelFor(m => m.Amount)
        @Html.TextBoxFor(m => m.Amount)
        @Html.ValidationMessageFor(m => m.Amount)
        <button type="button" class="remove">Remove</button> // add button
    </div>
}

在主视图中,您的脚本将是

var url = '@Url.Action("Recipient")';
var recipients = $('#recipients');
$('#add').click(function () {
    $.get(url, function (response) {
        recipients.append(response);
    });
});
$('#recipients').on('click', '.remove', (function() {
    var container = $(this).closest('.item');
    var id = container.data('id');
    if (!id) {
        container.remove();
    } else {
        // see notes below
    }
}

对于已添加到视图中的任何项目,属性ID 的值将为nullif 块中的代码将从视图中删除该项目。但是,对于您可能正在编辑的现有项目(ID 具有值),您需要考虑如何将其从数据库中删除。选项包括

  1. 在视图模型中添加一个额外的属性(比如)public bool IsDeleted { get; set; } 并在部分中包含一个隐藏的输入 为了它。然后您可以将其设置为true,这样当您提交时,您可以 删除所有recipients.Where(x =&gt; x.IsDeleted);

    @Html.HiddenFor(m => m.IsDeleted, new { @class = "flag" })
    
    } else {
        container.find('.flag').val('true');
    }
    
  2. 对服务器方法进行 ajax 调用,从 数据库,如果成功,删除关联的容器 来自 DOM

    } else {
        $.post(yourDeleteUrl, { id: id }, function(response) {
            if(response) {
                container.remove()
            } else {
                // oops, something went wrong
            }
        });
    }
    

【讨论】:

  • 这很好,但是部分中的封闭 div 永远不会获得 ID,因此 else 块永远不会运行。
  • “新”项目不需要它(data-id="@Model.ID" 仅在您编辑现有项目时适用 - else 块中的代码仅适用于删除现有项目)跨度>
  • 这可以按原样工作,甚至不需要 IsDeleted 标志或 ajax 调用,因为列表是从帖子视图构成的。那时我可以从列表中更新数据库。如果我想在 before 提交列表中删除项目(以防用户在提交之前重新加载页面),我只需要使用检查 !ID 的 if 语句。
  • 我明白这一点,但即使是现有项目似乎也没有 ID。我可以通过发出一些警告,即使对于现有项目,else 块也永远不会运行。
  • 你是什么意思他们没有ID - 如果你创建了一些然后保存到数据库中,然后稍后再回来编辑它们,那么他们必须有一个ID
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多