1

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 -->
Rena
  • 30,832
  • 6
  • 37
  • 72
  • @Rena : Oh whoa, what an answer ! Fantastic. This is so useful for me and hopefully others. Just for curiosity, is one solution more recommended than the other ? – lbrettsinclair May 05 '22 at 10:36
  • The first way looks more easier but it will generate more modal html code if you contain many records. The second way will always contain one modal html code. – Rena May 06 '22 at 00:56
  • Thank you- I do have one little problem now, once it's deleted, I repopulate my partialmodel that constains my row, then I call : ` code` return Json(new { isValid = true, html = JavaScriptConvert.RenderRazorViewToString(this, "_Match_StatsViewAll", match_StatsForAGame) }); `code` and it not rendering the view - it's not finding the view I guess in the controller. Since a now a Partial is calling a partial, I'm not sure what to change on that line. – lbrettsinclair May 06 '22 at 01:16
  • Your modal button click and it will submit the form to the backend and return Json(xxx), right? Or did you use ajax to call the api. Not sure how do you do, any way pls post a new thread and share the detailed code to us. – Rena May 06 '22 at 01:22
  • yes - the model button click calls for the submit form on the backend - which then return the json `
    `
    – lbrettsinclair May 06 '22 at 01:47
  • If you just use form submit, why you use return json.... Seems strange. Suggest you can post a new thread and explain details with code. – Rena May 06 '22 at 02:29

1 Answers1

1

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

Rena
  • 30,832
  • 6
  • 37
  • 72
  • 1
    Not sure what's the version, if you use .NET 6, you need change `data-dismiss="modal"` to `data-bs-dismiss="modal"`. – Rena May 04 '22 at 04:06