javascriptasp.net-coreajax.beginform

How can I pass input value in a complex Model from View to Controller?


My scenario here is that on my View, I have multiple field to input number and one field to auto generated result by a formula. I want to be able to pass those value back to my Controller, from there I will calculate and return the result back to View while the input value to calculate still remain. The reason why I don't perform this on my Javascript is because there are some condition that require me to interact with value from lots of others field in others data in database. I intend to do this by passing a whole set of Model from View to Controller, and I don't want to reload the page whenever an input field is input. So far, here's my two methods:

Using Javascript Ajax:

var modelObject = @Html.Raw(Json.Serialize(Model));

This allow me to store and passing Base Model at the beginning only. I can't pass new input value. Is there away for the input to automatically store their value in Model to be used in the code similar to the above?

Using Unobtrusive AJAX and Javascript to activate submit action:

function submit(){
    $('#formSubmit').submit();
    --OR--
    $('#btnSubmit').click();
}

<form id="formSubmit" data-ajax="true" asp-action="Action" method="POST">
    <input asp-for="Item.inputValue" onchange="submit()"/>
    <button id="btnSubmit" type="submit"></button>
</form>

The button when click works fine with Unobtrusive AJAX. But the Javascript to activate the submit event can't. My page still reload.

What is the right way for me to go? And in which of them, how do I need to fix my code to make it run like I want?


Solution

  • Using Javascript Ajax:

    var modelObject = @Html.Raw(Json.Serialize(Model));
    

    This allow me to store and passing Base Model at the beginning only. I can't pass new input value. Is there away for the input to automatically store their value in Model to be used in the code similar to the above?

    When using JQuery Ajax to pass the data, you should use the serialize() method to serialize the form, then pass the form data to the controller action method. Code as below:

            $("#btnAjax").click(function () {
                // var data = $("#mainform").serialize(); //you could set a break point to check the value.
                $.ajax({
                    url:"/Test/CreateProduct", // change the url to yours.
                    method: "Post",
                    data: $("#mainform").serialize(),
                    success: function (response) {
                        //after getting the response, update the content.
                        $("#div_partial").html("");
                        $("#div_partial").html(response);  //
                    },
                    error: function (error) {
                        alert("error");
                    }
                });
            });
    

    Using Unobtrusive AJAX and Javascript to activate submit action:

    function submit(){
        $('#formSubmit').submit();
        --OR--
        $('#btnSubmit').click();
    }
    
    <form id="formSubmit" data-ajax="true" asp-action="Action" method="POST">
        <input asp-for="Item.inputValue" onchange="submit()"/>
        <button id="btnSubmit" type="submit"></button>
    </form>
    

    The button when click works fine with Unobtrusive AJAX. But the javascript to activate the submit event can't. My page still reload.

    When using the jQuery Unobtrusive AJAX, first, please make sure you have added the jQuery Unobtrusive AJAX reference in current page, then, make sure you have activated unobtrusive Ajax on the target element.

    For example, using the following code, after clicking the submit button, it will submit the mainform to the ProductIndex action method, then update the div_partial contents:

        <form asp-action="ProductIndex" id="mainform" 
              data-ajax="true" 
              data-ajax-method="Post"
              data-ajax-update="#div_partial">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div id="div_partial"> 
                <partial name="_PVProduct.cshtml" data="@Model" />
            </div> 
            <div class="form-group">
                <input type="submit" value="Submit" class="btn btn-primary" /> 
            </div>
        </form>
    

    More detail information about using jQuery Unobtrusive AJAX, refer this link.

    The detail sample code as below:

    Model:

    public class Item
    {
        public int ItemId { get; set; }
        public string ItemDescription { get; set; } 
        public decimal ItemUnitPrice { get; set; }
        public decimal Quantity { get; set; }
    }
    
    public class ProductViewModel
    {
        public string UserName { get; set; }
        public List<Item> Items { get; set; }
    }
    

    Controller:

        public IActionResult ProductIndex()
        {
            ProductViewModel newitem = new ProductViewModel()
            {
                Items = _repository.GetItemViewModels().Select(c => new Item() { ItemId = c.ItemId, ItemDescription = c.ItemDescription, Quantity = c.Quantity, ItemUnitPrice = c.ItemUnitPrice }).ToList()
            };
    
    
            return View(newitem);
        }
        // Unobtrusive AJAX Post method
        [HttpPost]
        public IActionResult ProductIndex(ProductViewModel product)
        {
            return PartialView("_PVProduct", product);
        }
        //JQuery Ajax Post method.
        [HttpPost]
        public IActionResult CreateProduct(ProductViewModel product)
        { 
            return PartialView("_PVProduct", product);
        }
    

    PartialView (_PVProduct.cshtml): Here I use a partial view to display the Model content, it is easier to update the content with Ajax.

        @model WebApplication6.Models.ProductViewModel
    
            <div class="form-group">
                <label asp-for="UserName" class="control-label"></label>
                <input asp-for="UserName" class="form-control" />
                <span asp-validation-for="UserName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <table class="table">
                    <thead>
                        <tr>
                            <th>
                                ItemId
                            </th>
                            <th>
                                ItemDescription
                            </th>
                            <th>
                                ItemUnitPrice
                            </th>
                            <th>
                                Quantity
                            </th>
                            <th></th>
                        </tr>
                    </thead>
                    <tbody>
                        @for (var i = 0; i < Model.Items.Count(); i++)
                        {
                            <tr>
                                <td>
                                    @Model.Items[i].ItemId
                                    <input asp-for="Items[i].ItemId" type="hidden" />
                                </td>
                                <td>
                                    @Model.Items[i].ItemDescription
                                    <input asp-for="Items[i].ItemDescription" type="hidden" />
                                </td>
                                <td class="text-right">
                                    <input asp-for="Items[i].ItemUnitPrice" type="text" />
                                </td>
                                <td class="text-right">
                                    <input asp-for="Items[i].Quantity" type="text" />
                                </td>
                                <td class="text-right">
                                    @(Model.Items[i].Quantity * Model.Items[i].ItemUnitPrice)
                                </td>
                                <td></td>
                            </tr>
                        }
                    </tbody>
                </table>
            </div>
    

    View Page ():

    @model WebApplication6.Models.ProductViewModel
     
    <div class="row">
        <div class="col-md-4">
            <form asp-action="ProductIndex" id="mainform" 
                  data-ajax="true" 
                  data-ajax-method="Post"
                  data-ajax-update="#div_partial">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <div id="div_partial"> 
                    <partial name="_PVProduct.cshtml" data="@Model" />
                </div> 
                <div class="form-group">
                    <input type="submit" value="Submit" class="btn btn-primary" />
                    <input type="button" value="Ajax Submit" class="btn btn-primary" id="btnAjax" />
                </div>
            </form>
        </div>
    </div>
    

    At the end the above view page, add the following scripts: Here I use the jQuery Unobtrusive AJAX CDN reference:

    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-ajax-unobtrusive/3.2.6/jquery.unobtrusive-ajax.min.js"></script>
        <script>
            $(function () {
                $("#btnAjax").click(function () {
                    //var data = $("#mainform").serialize();
                    $.ajax({
                        url:"/Test/CreateProduct", // change the url to yours.
                        method: "Post",
                        data: $("#mainform").serialize(),
                        success: function (response) {
                            //after getting the response, update the content.
                            $("#div_partial").html("");
                            $("#div_partial").html(response); 
    
                            //attach change event and then trigger the submit form action..
                            $(".table> tbody >tr").each(function (index, tr) {
                                $(tr).find("input[name$='Quantity']").change(function () {
                                    //console.log($(this).val());
                                    $("#btnAjax").click();
                                });
                            });
                        },
                        error: function (error) {
                            alert("error");
                        }
                    });
                });
                //attach change event and then trigger the submit form action.
                $(".table> tbody >tr").each(function (index, tr) {
                    $(tr).find("input[name$='Quantity']").change(function () {
                        //console.log($(this).val());
                        $("#btnAjax").click();
                    });
                });
            })
        </script>
    }
    

    The output as below:

    enter image description here