Search code examples
c#jqueryasp.net-corerazorasp.net-core-mvc

Jquery/Ajax to update a TABLE[ASP.NET Core MVC]


I'm not sure how to refresh table data after I use AJAX Jquery.

I need help. I've a razor view, on button click button I am sending a post request with textbox and dropdown selected values, then in controller, passed Json response status for toaster.

The next controller returns a view and displays toaster status correctly.

The main problem is that I don't know how to refresh that table with newly inserted records after toaster response status.

This is my view of the Controller:

@using SimplCommerce.WebHost.Models @model dynamic
<body>
    <form method="post" id="map_Form">

        <table id="tbl_btn">
            <tr>
                <td align="center">
                    <button type="submit">Catalog Mapping</button>
                </td>
            </tr>
        </table>

        <table id="tb_properties" style="width:100%">
            <tr>
                @foreach (ApiMapDbViewModel itemApiProp in Model.dynApiPropModel)
                {
                    <td>
                        <input type="text" value="@itemApiProp.Key" readonly="readonly" />
                        <hr />

                        <select>
                            <option value="">-Select-</option>
                            @foreach (ApiMapDbViewModel itemK360Prop in Model.dynK360PropModel)
                            {
                                <option>@itemK360Prop.Key</option>

                            }
                        </select>
                    </td>
                }
            </tr>
        </table>

        <div id="partial_div">
            @Html.Partial("KPartialIndex")
        </div>

    </form>
</body>
</html>

@section scripts{

    <script>
        $(function () {
            $("button[type='submit']").click(function () {
                event.preventDefault();
                var properties = [];
                $("#tb_properties tr:first").find("td").each(function (index, item) {
                    var propertyname = $(item).find("input[type='text']").val();
                    var selctedvalue = $(item).find("select").val();
                    properties.push('"' + propertyname + '":"' + selctedvalue + '"');
                });
                var jsonstr = '{' + properties.join(",") + '}';
                var jsobject = JSON.parse(jsonstr);

                $.ajax({
                    type: "Post",
                    url: "/KMap/Insert",
                    data: { jsonModel: jsobject },
                    success: function (response) {
                        toastr.error(response.status + "----->" + response.message);
                        //info//warning//error//success
                        toastr.options = {
                            "closeButton": false,
                            "debug": false,
                            "newestOnTop": false,
                            "progressBar": false,
                            "positionClass": "toast-top-center",
                            "preventDuplicates": false,
                            "onclick": null,
                            "showDuration": "1000",
                            "hideDuration": "1000",
                            "timeOut": "5000",
                            "extendedTimeOut": "1000",
                            "showEasing": "swing",
                            "hideEasing": "linear",
                            "showMethod": "fadeIn",
                            "hideMethod": "fadeOut"
                        };

                        $("#map_Form select").val("");
                        $("#partial_div").load("/KMap/LoadPartialViewOnPost"); // not working

                    },
                    error: function (xhr, textStatus, errorThrown) {
                        console.log('in error');
                    }
                });
            });
        });

    </script>
}

This is my partial view:

 @using SimplCommerce.WebHost.Models @model dynamic
<table>   
    @if (Model.dynMappedDataModel != null)

    {
        @foreach (K360mapMaster itemMappedData in Model.dynMappedDataModel)
        {
            <tr>
                <td>@itemMappedData.ClientCatalog</td>
                <td>@itemMappedData.K360catalog</td>
            </tr>
        }

    }
</table>

This is my controller:

 public IActionResult Index()
    {
        dynamic dynModel = new ExpandoObject();
        dynModel.dynApiPropModel = GetListApiProp();
        dynModel.dynMappedDataModel = ListMappedData();
        dynModel.dynK360PropModel = GetListK360Prop();
        return View(dynModel);
    }

    [HttpPost]
    public IActionResult LoadPartialViewOnPost()
    {
        dynamic mymodel = new ExpandoObject();
        mymodel.dynMappedDataModel = ListMappedData();
        return PartialView("KPartialIndex", mymodel);
    }

    public List<K360mapMaster> ListMappedData()
    {
        List<K360mapMaster> items = new List<K360mapMaster>();
        var query = from K360mapMaster in _context.K360mapMasters
                    select K360mapMaster;
        var mappings = query.ToList();
        foreach (var mappingData in mappings)
        {
            items.Add(new K360mapMaster()
            {
               
                ClientCatalog = mappingData.ClientCatalog,
                K360catalog = mappingData.K360catalog

            });
        }
        return items;
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Insert(ApiJsonViewModel jsonModel)
    {
        if (!ModelState.IsValid)
        {
            var errors = ModelState.SelectMany(x => x.Value.Errors, (y, z) => z.Exception.Message);
            return BadRequest(errors);
        }
        Type type = jsonModel.GetType();
        PropertyInfo[] props = type.GetProperties();
        List<K360mapMaster> K360mapListObj = new List<K360mapMaster>();

        K360mapListObj = props.Where(c => !string.IsNullOrEmpty(c.GetValue(jsonModel, null)?.ToString()))
                                        .Select(c => new K360mapMaster() { ClientCatalog = c.Name, K360catalog = c.GetValue(jsonModel, null)?.ToString() })
                                        .ToList();
        if (K360mapListObj.Count > 0)
        {
            try
            {
                var ListCatalogs = K360mapListObj.Select(l => l.ClientCatalog).ToList();

                foreach (var item in ListCatalogs)
                {
                    var DbCatalogs = (from p in _context.K360mapMasters
                                      where p.ClientCatalog == item
                                      select p).FirstOrDefault();
                    if (DbCatalogs != null)
                    {

                        return Json(new { Status = "This is an information notification provided by K360 eCommerce. ", Message = "Selected catalog  " + item + "  already mapped." });
                    }
                }
                _context.K360mapMasters.AddRange(K360mapListObj);
                _context.SaveChanges();                   
               return Json(new { Status = "This is a success notification from K360 eCommerce. ", Message = "Product catalog's mapped sucessfully." });
            }
            catch
            {
                return Json(new { Status = "This is an error notification provided by K360 eCommerce. ", Message = "Mapping failed" });
            }
        }
        else
        {
            return Json(new { Status = "This is a warning notification provided by K360 eCommerce. ", Message = "No product catalog selected." });
        }

    }

I want to refresh the new insert records after toaster response status. Please help thanks

The issue is fixed now.

Provided id for the table in partial view.

and in Jquery Sucess function added below piece of code

  $("#par_tbl").load(window.location.href + " #par_tbl");

Solution

  • You could use JQuery to loop through the <td> elements, and use JQuery Selector gets the property name and selected value. Then, according to the value to generate a JS object, and use JQuery Ajax to call the controller action method and store the object into the database.

    Please refer the following sample code:

    Models:

    public class SMJsonModel
    {
        public string title { get; set; }
        public string type { get; set; }
        public string description { get; set; }
        public string fileName { get; set; }
        public string height { get; set; }
        public string width { get; set; }
        public string price { get; set; }
        public string rating { get; set; }
    }
    public class PropertyInfoK360
    {
        public string Value { get; set; }
        public string Key { get; set; }
    }
    

    Controller:

    public class SupermarketController : Controller
    {
        public IActionResult Index()
        {
            //initial data:
            List<SMJsonModel> JsonResultList = new List<SMJsonModel>()
            {
                new SMJsonModel(){
                    title="Brown eggs",
                    type="dairy",
                    description="Raw organic brown eggs in a basket",
                    fileName="0.jpg",
                    height = "600",
                    width="400",
                    price="28.1",
                    rating="4"
                }
            };
            ViewData["K360DbPropVD"] = new List<PropertyInfoK360>()
            {
                new PropertyInfoK360(){ Value="AAA", Key="AAA"},
                 new PropertyInfoK360(){ Value="BBB", Key="BBB"},
                  new PropertyInfoK360(){ Value="CCC", Key="CCC"},
                   new PropertyInfoK360(){ Value="DDD", Key="DDD"},
                    new PropertyInfoK360(){ Value="EEE", Key="EEE"},
                     new PropertyInfoK360(){ Value="FFF", Key="FFF"},
                      new PropertyInfoK360(){ Value="GGG", Key="GGG"},
            };
            return View(JsonResultList);
        }
        // this method is used to insert data into database.
        [HttpPost]
        public IActionResult Insert(SMJsonModel jsonModel)
        {
            //insert object into database.
    
            return Ok("success");
        }
    }
    

    Index View page:

    @model IEnumerable<netcore5.Models.SMJsonModel> 
    <div class="container">
        <table class="table table-striped table-bordered" id="tb_properties" style="width:100%">
            <thead>
            </thead>
            <tbody>
                <tr>
                    @foreach (var property in Model.GetType().GetGenericArguments()[0].GetProperties())
                    {
                        <td>
                            <input type="text" value="@property.Name" class="form-control" />
                            @{var K360list = new SelectList((System.Collections.IEnumerable)ViewData["K360DbPropVD"], "Value", "Key");}
                            <select asp-items="K360list" class="form-control"></select>
    
                        </td>
                    }
                </tr>
            </tbody>
        </table>
    </div>
    <div class="container">
        <table class="table table-striped table-bordered" style="width:100%">
            <tr>
                <td align="center">
                    <button type="submit" class="btn btn-primary">Catalog Mapping</button>
                </td>
            </tr>
        </table>
    </div>
    
    @section scripts{
    <script>
        $(function () {
            $("button[type='submit']").click(function () {
                event.preventDefault();
                var properties = []; //define an array to store the property name and the selected value.
                $("#tb_properties tr:first").find("td").each(function (index, item) {
                    var propertyname = $(item).find("input[type='text']").val();
                    var selctedvalue = $(item).find("select").val(); 
                    properties.push('"' + propertyname + '":"' + selctedvalue + '"');
                }); 
                //According the properties to genereate the json string.
                var jsonstr = '{' + properties.join(",") + '}';
                //convert the json string to js object.
                var jsobject = JSON.parse(jsonstr);
                //call the Inset method and store data into the database.
                $.ajax({
                    type: "Post",
                    url: "/Supermarket/Insert",
                    data: { jsonModel: jsobject },
                    success: function (response) {
                        console.log(response); 
    
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        console.log('in error');
                    }
                });
            });
        });
    </script>
    }
    

    The screenshot as below:

    enter image description here

    Update

    As mentioned in the comment, to store the JsModel's property name as the first column and its value as the second column's value in the K360ECommerceS table, you could refer the following code:

        [HttpPost]
        public IActionResult Insert(SMJsonModel jsonModel)
        {
            //insert object into database.
            //required using System.Reflection; 
            //use GetType() and GetProperties() method to get object's property name and its value.
            Type type = jsonModel.GetType();
            PropertyInfo[] props = type.GetProperties();
    
            List<K360Master> k360Masters = new List<K360Master>(); 
            foreach(var item in props)
            {
                K360Master master = new K360Master()
                {
                    ClientCatalog = item.Name,
                    K360catalog = item.GetValue(jsonModel, null)?.ToString()
                };
                k360Masters.Add(master);
            }
            _context.K360Master.AddRange(k360Masters);
            _context.SaveChanges();
            
            return Ok("success");
        }
    

    After that, the result in the K360Master table as below:

    enter image description here

    [Note] In the above sample, my DBContext as below, it will insert data into the K360Master table, please check your code and make sure you are using the correct Entity and Tables.

    public class ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    
        public DbSet<K360Master> K360Master { get; set; }
    }
    

    Update

    Only if we select all the 8 dropdownlist then only it gets inserted. Not able to select only 2 or 3 dropdownlist and it shows Cannot insert the value NULL into column 'K360Catalog'. Its not null column. please guide me. task needs to finished by today eod

    In the Insert method, you could check whether the value is null or not before save them to database. Code as below:

        [HttpPost]
        public IActionResult Insert(SMJsonModel jsonModel)
        {
            //insert object into database.
    
            Type type = jsonModel.GetType();
            PropertyInfo[] props = type.GetProperties();
    
            List<K360Master> k360Masters = new List<K360Master>(); 
            foreach(var item in props)
            {
                //check if the value is null or not.
                if(!string.IsNullOrEmpty(item.GetValue(jsonModel, null)?.ToString()))
                {
                    K360Master master = new K360Master()
                    {
                        ClientCatalog = item.Name,
                        K360catalog = item.GetValue(jsonModel, null)?.ToString()
                    };
                    // if the value is not null, add it to the list
                    k360Masters.Add(master);
                }
            }
            //insert the list items into database.
            _context.K360Master.AddRange(k360Masters);
            _context.SaveChanges();
            
            return Ok("success");
        }
    

    The screenshot as below:

    enter image description here

    Update

    From your description, if you don't want to use for each statement to loop through the 8 fields, you could try to use LINQ where clause to filter the data. And, if you want to return multiple value from controller action method to the Ajax function, you could refer a Json result. please check the following sample:

        [HttpPost]
        public IActionResult Insert(SMJsonModel jsonModel)
        {
            //insert object into database.
    
            Type type = jsonModel.GetType();
            PropertyInfo[] props = type.GetProperties();
    
            List<K360Master> k360Masters = new List<K360Master>(); 
            //using where clause to filter data.
            k360Masters = props.Where(c => !string.IsNullOrEmpty(c.GetValue(jsonModel, null)?.ToString()))
                                            .Select(c=> new K360Master() { ClientCatalog= c.Name,  K360catalog = c.GetValue(jsonModel, null)?.ToString() })
                                            .ToList(); 
            if(k360Masters.Count > 0)
            {
                try
                {
                    //foreach (var item in props)
                    //{
                    //    //check if the value is null or not. if the value is not null, add it to the list
                    //    if (!string.IsNullOrEmpty(item.GetValue(jsonModel, null)?.ToString()))
                    //    {
                    //        K360Master master = new K360Master()
                    //        {
                    //            ClientCatalog = item.Name,
                    //            K360catalog = item.GetValue(jsonModel, null)?.ToString()
                    //        };
                    //        k360Masters.Add(master);
                    //    }
                    //}
    
                    _context.K360Master.AddRange(k360Masters);
                    _context.SaveChanges();
    
                    return Json(new { Status = "Success", Message = "Insert Success!" }); 
                }
                catch (Exception)
                {
                    return Json(new { Status = "Error", Message = "Fail to insert data into database" });
                }
            }
            else
            {
                return Json(new { Status = "Warning", Message = "No selected item" });
            }
        }
    

    Ajax code:

            //According the properties to genereate the json string.
            var jsonstr = '{' + properties.join(",") + '}';
            //convert the json string to js object.
            var jsobject = JSON.parse(jsonstr);
            $.ajax({
                type: "Post",
                url: "/Supermarket/Insert",
                data: { jsonModel: jsobject },
                success: function (response) {
                    alert(response.status + "--" + response.message);
                    //then, based on the status to choose 
                },
                error: function (xhr, textStatus, errorThrown) {
                    console.log('in error');
                }
            });
    

    The result like this:

    enter image description here