简体   繁体   中英

asp.net core mvc model binding with jquery repeater

I am using jquery repeater in my form to dynamically add only a part of input group to form. I did try but couldn't get inputs bind to model, I went blind.

Here my model.

public class SuggestionCreateEditViewModel
{
    public Guid[] DetectionId { get; set; }

    public SuggestionCreateEditRepeatedModel[] Repeated { get; set; }

}
public class SuggestionCreateEditRepeatedModel
{
    public Guid To { get; set; }

    public string Description { get; set; }

    public DateTime Deadline { get; set; }
}

Form, I removed a lot of parts of form for brevity

<div class="col-lg-9 col-md-9 col-sm-12">
    <select asp-for="DetectionId" asp-items="ViewBag.AllDetections" class="m-bootstrap-select m_selectpicker toValidate" 
            multiple data-actions-box="true" data-width="100%"></select>
</div>
<div class="col-lg-9 col-md-9 col-sm-12 input-group date">
    <input name = "Repeated.Deadline" type="text" readonly class="form-control toValidate dtDueDate" />
</div>
<div class="col-lg-12 col-md-12 col-sm-12">
    <textarea name = "Repeated.Description" class="form-control toValidate txtSuggestion" type="text" >
    </textarea>
</div>

after adding a new repeated section to form and before posting it to server, if I form.serailizeArray() it returns collection like as follows (what jquery form repeater dynamically shape names I believe)

{name: "DetectionId", value: "afca1b82-0455-432e-c780-08d6ac38b012"}
{name: "[0][Repeated.To][]", value: "b1176b82-1c25-4d13-9283-df2b16735266"}
{name: "[0][Repeated.Deadline]", value: "04/04/2019"}
{name: "[0][Repeated.Description]", value: "<p>test 1</p>"}
{name: "[1][Repeated.To]", value: "188806d8-202a-4787-98a6-8dc060624d93"}
{name: "[1][Repeated.Deadline]", value: "05/04/2019"}
{name: "[1][Repeated.Description]", value: "<p>test 2</p>"}

and my controller

[HttpPost]
public IActionResult CreateSuggestion(SuggestionCreateEditViewModel model, IFormFile[] documents)
        {...

controller couldn't get Repeated binded, only DetectionId is binded. How should I shape my model to get the data?

Here is a working demo for with jquery.repeater.js , pay attention to this line <div data-repeater-list="Repeated"> which will format the field like name="Repeated[0][Description]"

@model TestCore.Models.SuggestionCreateEditViewModel
@{
    ViewData["Title"] = "Contact";
}

<form class="repeater" asp-action="CreateSuggestion" method="post">
    <!--
        The value given to the data-repeater-list attribute will be used as the
        base of rewritten name attributes.  In this example, the first
        data-repeater-item's name attribute would become group-a[0][text-input],
        and the second data-repeater-item would become group-a[1][text-input]
    -->
    <div data-repeater-list="Repeated">
        <div data-repeater-item>
            <div class="col-lg-9 col-md-9 col-sm-12">
                <select asp-for="DetectionId" asp-items="ViewBag.AllDetections" class="m-bootstrap-select m_selectpicker toValidate"
                        multiple data-actions-box="true" data-width="100%"></select>
            </div>
            <div class="col-lg-12 col-md-12 col-sm-12">
                <textarea name="Description" class="form-control toValidate txtSuggestion" type="text">
                </textarea>
            </div>
        </div>
    </div>
    <input data-repeater-create type="button" value="Add" />
    <input type="submit" value="Submit"/>
</form>
@section Scripts{
    <!-- Import repeater js  -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.repeater/1.2.1/jquery.repeater.js"></script>
    <script>
        $(document).ready(function () {
            $('.repeater').repeater({
                // (Optional)
                // start with an empty list of repeaters. Set your first (and only)
                // "data-repeater-item" with style="display:none;" and pass the
                // following configuration flag
                initEmpty: true,

                // (Optional)
                // "show" is called just after an item is added.  The item is hidden
                // at this point.  If a show callback is not given the item will
                // have $(this).show() called on it.
                show: function () {
                    $(this).slideDown();
                },
                // (Optional)
                // "hide" is called when a user clicks on a data-repeater-delete
                // element.  The item is still visible.  "hide" is passed a function
                // as its first argument which will properly remove the item.
                // "hide" allows for a confirmation step, to send a delete request
                // to the server, etc.  If a hide callback is not given the item
                // will be deleted.
                hide: function (deleteElement) {
                    if (confirm('Are you sure you want to delete this element?')) {
                        $(this).slideUp(deleteElement);
                    }
                },

                // (Optional)
                // Removes the delete button from the first list item,
                // defaults to false.
                isFirstItemUndeletable: true
            })
        });    
    </script>
}

By the looks of things, the controller cannot bind the repeater properties back to your view model because the naming of the posted content does not match the naming in your view model (as Topher mentioned).

The DetectionId is named correctly though because the name of the property matches and its not an array.

To resolve an array we need to make sure we include the property name in the form as well as an index so that mvc model binding knows where to bind the result to.

With that, can you try changing the format of the name to:

That should match up with your controller and correctly bind.

For more info on binding, please see this .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM