Search code examples
javascriptasp.net-core-mvcbootstrap-modal

Bootstrap Modal Confirmation using ASP.Net MVC and a table


Using MVC .NetCore, I populate a "partial" view and a Table. Within that table, a list of records. Each row have a button to edit or delete. To delete a record, I need to have 4 IDs since the PK is made of those 4 keys. I was able to make it work with a javascript, however, I do not like the "confirm" display being produce. I would like to have a more elegant way and use a modal form for this. But how do I retrieve the 4 values when clicking a button in of the row?

  • Here is a Row being populated from my Model:
<td>
    <div>
        <a onclick="showInPopup('@Url.Action("Match_StatsCreateOrEdit","Match_Stats",new {comp_id=item.Match_Stats.Comp_Id, team_id=item.Match_Stats.Team_Id,match_id=item.Match_Stats.Match_Id, match_Stat_Id=item.Match_Stats.Match_Stat_Id},Context.Request.Scheme)','Update A Stat')" class="btn btn-primary btn-xs"><i class="fas fa-pencil-alt"></i> Edit</a>
                    
        <form asp-action="Match_StatsDelete" asp-route-comp_Id="@item.Match_Stats.Comp_Id" asp-route-team_Id="@item.Match_Stats.Team_Id" asp-route-Match_Id="@item.Match_Stats.Match_Id"
                          asp-route-Match_Stat_Id="@item.Match_Stats.Match_Stat_Id" onsubmit="return jQueryAjaxDelete(this)" class="d-inline">
                        <button type="submit" class="btn btn-warning btn-xs"><i class="fas fa-trash"></i> Delete</button>
          </form>
                    
      </div>
</td>
  • Here is the Javascript currently used:
jQueryAjaxDelete = form => {
    if (confirm('Are you sure want to delete this record ?')) {
        try {
            $.ajax({
                type: 'POST',
                url: form.action,
                data: new FormData(form),
                contentType: false,
                processData: false,
                success: function (res) {
                    $('#view-all').html(res.html);
                    $.notify('Deleted Successfully !', {
                        globalPostion: 'Top Center',
                        className: 'success'
                    });
                },
                error: function (err) {
                    console.log(err)
                }
            })
        } catch (ex) {
            console.log(ex)
        }
    }

    //prevent default form submit event
    return false;
}
  • Here is the Model I would like to use. How do I get the 4 ID into this?
<!-- /.modal -->
<div class="modal fade" id="modal-removeplayers">
    <div class="modal-dialog modal-sm">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title">Confirmation needed</h4>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <p>Do you really want to delete this record ?</p>
            </div>
            <div class="modal-footer justify-content-between">
                <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>


                <!-- CODE HERE TO RETRIEVE All 4 IDs and Call the "delete" on the Controller -->>

            </div>
        </div>
        <!-- /.modal-content -->
    </div>
    <!-- /.modal-dialog -->
</div>
<!-- /.modal -->

Solution

  • One way is that put the modal inside the loop:

    Model:

    public class Test
    {
        public Match_Stats Match_Stats { get; set; }
        //other properties....
    }
    public class Match_Stats
    {
        public int Comp_Id { get; set; }
        public int Team_Id { get; set; }
        public int Match_Id { get; set; }
        public int Match_Stat_Id { get; set; }
        //other properties.....
    }
    

    View(Index.cshtml):

    @model IEnumerable<Test>
    @{
        int i = 0;
    }
    @foreach (var item in Model)
    {
        //other code.....
        <a onclick="showInPopup('@Url.Action("Match_StatsCreateOrEdit","Match_Stats",new {comp_id=item.Match_Stats.Comp_Id, team_id=item.Match_Stats.Team_Id,match_id=item.Match_Stats.Match_Id, match_Stat_Id=item.Match_Stats.Match_Stat_Id},Context.Request.Scheme)','Update A Stat')" class="btn btn-primary btn-xs"><i class="fas fa-pencil-alt"></i> Edit</a>
        
        //add the button to launch the modal
        <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#modal-removeplayers_@i"><i class="fas fa-trash"></i> Delete</button>
    
        <div class="modal fade" id="modal-removeplayers_@i">
        <div class="modal-dialog modal-sm">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title">Confirmation needed</h4>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <div class="modal-body">
                    <p>Do you really want to delete this record ?</p>
                </div>
                <div class="modal-footer justify-content-between">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
          //move the form to here.....
                    <form asp-action="Match_StatsDelete" asp-route-comp_Id="@item.Match_Stats.Comp_Id" asp-route-team_Id="@item.Match_Stats.Team_Id" asp-route-Match_Id="@item.Match_Stats.Match_Id"
                asp-route-Match_Stat_Id="@item.Match_Stats.Match_Stat_Id" class="d-inline">
                          <button type="submit" class="btn btn-warning btn-xs"><i class="fas fa-trash"></i> Delete</button>
    
                    </form>
                </div>
            </div>
        </div>
        </div>
        i++;     //add this...
    }
    

    Controller:

    public IActionResult Index()
    {
        //hard-coded the data just for easy testing!!!
        var model = new List<Test>()
        {
            new Test(){Match_Stats=new Match_Stats(){Comp_Id=1,Match_Id=11,Match_Stat_Id=12,Team_Id=13}},
            new Test(){Match_Stats=new Match_Stats(){Comp_Id=2,Match_Id=21,Match_Stat_Id=22,Team_Id=23}},
            new Test(){Match_Stats=new Match_Stats(){Comp_Id=3,Match_Id=31,Match_Stat_Id=32,Team_Id=33}}
        };
        return View(model);
    }
    [HttpPost]
    public IActionResult Match_StatsDelete(int Comp_Id,int Match_Id, int Match_Stat_Id,int Team_Id)
    {
        //do your stuff.......
    }
    

    The second way, you can use partial view to reuse the modal and use ajax to invoke the partial view.

    Model:

    public class Test
    {
        public Match_Stats Match_Stats { get; set; }
        //other properties....
    }
    public class Match_Stats
    {
        public int Comp_Id { get; set; }
        public int Team_Id { get; set; }
        public int Match_Id { get; set; }
        public int Match_Stat_Id { get; set; }
        //other properties.....
    }
    

    View(Index.cshtml):

    @model IEnumerable<Test>
    
    @foreach (var item in Model)
    {
        <a onclick="showInPopup('@Url.Action("Match_StatsCreateOrEdit","Match_Stats",new {comp_id=item.Match_Stats.Comp_Id, team_id=item.Match_Stats.Team_Id,match_id=item.Match_Stats.Match_Id, match_Stat_Id=item.Match_Stats.Match_Stat_Id},Context.Request.Scheme)','Update A Stat')" class="btn btn-primary btn-xs"><i class="fas fa-pencil-alt"></i> Edit</a>
        
        <button type="button" class="btn btn-primary" onclick="toggleModal('@item.Match_Stats.Comp_Id','@item.Match_Stats.Team_Id','@item.Match_Stats.Match_Id','@item.Match_Stats.Match_Stat_Id')"><i class="fas fa-trash"></i> Delete</button>
    }
    
    <div id="loadModal">
         <!--load the modal-->
    </div>
    @section Scripts
    {
    <script>
        function toggleModal(comp_id,team_id,match_id,match_Stat_Id) {
            var model = {
                comp_id : comp_id,
                team_id:team_id,
                match_id:match_id,
                match_Stat_Id:match_Stat_Id
            };
            $.ajax({
                type: "Post",
                url: "/Home/LoadPartial",
                data:model,
                success: function (data) {
                    $("#loadModal").html(data);
                    $('#modal-removeplayers').modal('show')
    
                }
            })
        }
    </script>
    }
    

    Partial View in /Views/Shared folder(Partial.cshtml):

    @model Match_Stats
    
    <div class="modal fade" id="modal-removeplayers">
        <div class="modal-dialog modal-sm">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title">Confirmation needed</h4>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <div class="modal-body">
                    <p>Do you really want to delete this record ?</p>
                </div>
                <div class="modal-footer justify-content-between">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                    <form asp-action="Match_StatsDelete" asp-route-comp_Id="@Model.Comp_Id" asp-route-team_Id="@Model.Team_Id" asp-route-Match_Id="@Model.Match_Id"
                asp-route-Match_Stat_Id="@Model.Match_Stat_Id" class="d-inline">
                          <button type="submit" class="btn btn-warning btn-xs"><i class="fas fa-trash"></i> Delete</button>
    
                    </form>
                </div>
            </div>
        </div>
    </div>
    

    Controller:

    public IActionResult Index()
    {
        //hard-coded the data just for easy testing!!!
        var model = new List<Test>()
        {
            new Test(){Match_Stats=new Match_Stats(){Comp_Id=1,Match_Id=11,Match_Stat_Id=12,Team_Id=13}},
            new Test(){Match_Stats=new Match_Stats(){Comp_Id=2,Match_Id=21,Match_Stat_Id=22,Team_Id=23}},
            new Test(){Match_Stats=new Match_Stats(){Comp_Id=3,Match_Id=31,Match_Stat_Id=32,Team_Id=33}}
        };
        return View(model);
    }
    [HttpPost]
    public IActionResult Match_StatsDelete(int Comp_Id,int Match_Id, int Match_Stat_Id,int Team_Id)
    {
        //do your stuff.......
    }
    [HttpPost]
    public IActionResult LoadPartial(Match_Stats model)
    {
        //hard-coded the data just for easy testing!!!
        var list = new List<Match_Stats>()
        {
            new Match_Stats(){Comp_Id=1,Match_Id=11,Match_Stat_Id=12,Team_Id=13},
            new Match_Stats(){Comp_Id=2,Match_Id=21,Match_Stat_Id=22,Team_Id=23},
            new Match_Stats(){Comp_Id=3,Match_Id=31,Match_Stat_Id=32,Team_Id=33}
        };
        var data = list.Where(a => a.Comp_Id == model.Comp_Id & a.Match_Id == model.Match_Id & a.Team_Id == model.Team_Id & a.Match_Stat_Id == model.Match_Stat_Id).FirstOrDefault();
        return PartialView("Partial", data);
    }
    

    Result:

    enter image description here