Как добавить несколько объектов на страницах Razor с динамическим HTML в редактируемый объект?

#asp.net-core #asp.net-ajax #razor-pages #dynamic-html

#asp.net-ядро #asp.net-ajax #razor-страницы #dynamic-html

Вопрос:

У меня есть ASP.NET Веб-приложение Core 3.0 с сгенерированными страницами razor. Модель следующая:

 public class Element
{
    public int ElementID { get; set; }
    public string Name { get; set; }
    public string Discriminator { get; private set; }
}

public class BucketListElement : Element
{
    public int BucketListID { get; set; }
    public string Description { get; set; }
    public bool Completed { get; set; }

    public BucketList BucketList { get; set; }
    public Progression Progression { get; set; }
}

public class Progression
{
    public int ProgressionID { get; set; }
    public int ElementID { get; set; }
    public ICollection<BLETask> BLETasks { get; set; }
    public BucketListElement BLElement { get; set; }
}

public class BLETask
{
    public int BLETaskID { get; set; }
    public int ProgressionID { get; set; }
    public string Text { get; set; }
    public bool Completed { get; set; }
    public Progression Progression { get; set; }
}
  

Элемент BucketListElement имеет 1 прогрессию. Прогрессия может иметь 0..* BucketListElementTasks (BLETask). После создания BucketListElement мы можем перейти на страницу редактирования, и там я хотел бы иметь возможность выполнить следующее:
Пользователь может нажать знак » «, который добавляет еще одно поле с флажком, или может нажать знак «-«, который удаляет поле с флажком рядом с ним. Каждое поле должно быть заполнено, и после сохранения столько BLETasks должно быть назначено редактируемому объекту BucketListElement Progression (через внешний ключ), сколько полей создал и заполнил пользователь.

Отредактируйте макет страницы, дважды щелкнув знак » » (требуется красная часть)

Если я знаю это правильно, я могу динамически манипулировать HTML, чтобы добавлять и удалять эти поля с помощью JavaScript / Ajax, но, к сожалению, у меня нет опыта в этом, поэтому я прошу вашей помощи.

ОБНОВЛЕНИЕ: с учетом предложенных изменений @mj1313 добавление BLETasks работало нормально, но я хотел иметь возможность редактировать уже зарегистрированные BLETasks, поэтому я вставил этот код в Edit.cshtml в с идентификатором «Задачи». Теперь это выглядит так:

 <div class="form-group">
<label asp-for="BucketListElement.Progression.BLETasks" class="control-label"></label>
<button id="addTask" class='btn btn-primary'> </button>
<div id="Tasks" style="margin-top:10px">
    @{
        int indexCounter = 0;
        int taskCounter = 1;
        foreach (var task in Model.BucketListElement.Progression.BLETasks)
        {
            <div class="taskRow">
                <label>Task @taskCounter:</label>
                <input class="form-control" asp-for="@Model.BucketListElement.Progression.BLETasks[indexCounter].Text" required="required" />
                <input class="largerCheckbox" asp-for="@Model.BucketListElement.Progression.BLETasks[indexCounter].Completed" />
                <button class="btn btn-danger" style="padding-top:1px" onclick="deleteRow(this)" value="@indexCounter">-</button>
            </div>
            indexCounter  ;
            taskCounter  ;
        }
    }
</div>
  

И теперь из уже существующих BLETasks можно удалить только последнюю строку (и те, которые были созданы скриптом (кнопка » «)). Если я нажму кнопку «-» в конце первой n-1 строки, это похоже на то, как если бы я нажал на кнопку сохранения.
Если я удалю текст одного обязательного поля (чтобы иметь возможность оставаться на странице) и нажму на одну из первых кнопок n-1 строки «-«, это произойдет:
После удаления обязательного поля и удаления одной из первых n-1 строк

Ответ №1:

Я сделал пример на основе вашего описания, вы можете обратиться к приведенным ниже кодам:

Edit.cshtml:

 @page
@model WebApplication9.Pages.EditModel
@{
}

<style>
    .largerCheckbox {
        width: 25px;
        height: 25px;
        margin-left: 20px;
        margin-right: 20px;
        vertical-align: middle
    }

</style>

<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="BucketListElement.Name" class="control-label"></label>
                <input asp-for="BucketListElement.Name" class="form-control" />
                <span asp-validation-for="BucketListElement.Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="BucketListElement.Description" class="control-label"></label>
                <input asp-for="BucketListElement.Description" class="form-control" />
                <span asp-validation-for="BucketListElement.Description" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="BucketListElement.Progression.BLETasks" class="control-label"></label>
                <button id="addTask" class='btn btn-primary'> </button>
                <div id="Tasks" style="margin-top:10px">

                </div>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>


@section scripts{
    <script>
        var count = 1;
        $("#addTask").on("click", function () {
            var htmlstring = "<div class='taskRow'><label>Task"   count   "</label>";
            htmlstring  = "<input type='text' name='BucketListElement.Progression.BLETasks["   (count - 1)  "].Text' required='required'>";
            htmlstring  = "<input type='checkbox' name='BucketListElement.Progression.BLETasks["   (count - 1)  "].Completed' class='largerCheckbox' value='true'>";
            htmlstring  = "<button class='btn btn-danger' style='padding-top:1px' onclick='deleteRow(this)' value='"   (count - 1) "'>-</button></div>"
            $("#Tasks").append(htmlstring);
            count  ;
        })

        function deleteRow(element) {
            var currentRow = parseInt($(element).val());
            let nextsiblings = document.querySelectorAll('.taskRow:nth-child('   (currentRow   1)   ') ~ *');
            for (var i = 0; i < nextsiblings.length; i  ) {
                var childElements = nextsiblings[i].children;
                childElements[0].textContent = "Task"   (currentRow   1);
                childElements[1].setAttribute("name", "BucketListElement.Progression.BLETasks["   currentRow   "].Text");
                childElements[2].setAttribute("name", "BucketListElement.Progression.BLETasks["   currentRow   "].Completed");
                childElements[3].setAttribute("value", currentRow)
                currentRow  ;
            }
            $(element).parent("div").remove();
            count--;
        }
    </script>

}
  

Edit.cshtml.cs:

 public class EditModel : PageModel
{
    [BindProperty]
    public BucketListElement BucketListElement { get; set; }

    public void OnGet()
    {
        BucketListElement = new BucketListElement
        {
            Name = "Element1",
            Description = "AAA"
        };
    }

    public void OnPost()
    {
        
    }
}
  

Результат:

введите описание изображения здесь

Комментарии:

1. Ваше предложение довольно точное и работает хорошо, но я внес некоторые изменения (ОБНОВЛЕНИЕ в исходном сообщении), и теперь кнопка «-» работает только в последней строке и в тех, которые были созданы скриптом, и я не знаю почему.

2. Изменить var childElements = nextsiblings[i].childNodes; на var childElements = nextsiblings[i].children;