Представление для добавления и удаления элементов из коллекции в том же представлении

Я создаю представление, которое позволяет пользователю добавлять и удалять объекты в списке определенным образом, который хочет клиент. Пользователь должен иметь возможность добавлять или удалять несколько форм на странице перед отправкой. Когда страница публикуется, ей необходимо отобразить то, что уже есть в списке, с возможностью удаления каждого элемента, а также разрешить пользователю добавлять / удалять дополнительные объекты перед повторной отправкой.

Я могу использовать JQuery и частичное представление, чтобы позволить пользователю добавлять или удалять новые формы перед отправкой. Я не могу понять, как предоставить кнопку для удаления объектов, которые уже есть в списке, из предыдущей отправки.

Кто-нибудь может мне помочь с этим? Это будет с благодарностью.

Вот что я понял до сих пор. По-моему:

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

1 ответ

Решение

Наличие единственной кнопки "удалить" не имеет смысла, и вам нужно "удалить", связанную с каждым элементом в коллекции. Кроме того, удалите id атрибуты из вашего <div> элементы и использовать относительные селекторы.

Измените частичное на

@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 будет null и код в if Блок удалит элемент из вида. Однако для существующих элементов, которые вы можете редактировать (где ID имеет значение), то вам нужно подумать, как удалить его из базы данных. Варианты включают

  1. Добавление дополнительного свойства в модель представления (скажем) public bool IsDeleted { get; set; } и включая скрытый вход в частичное для него. Затем вы можете установить его на true поэтому, когда вы отправляете, вы можете удалить все recipients.Where(x => 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
            }
        });
    }
    
Другие вопросы по тегам