Darkwingduck
Darkwingduck

Reputation: 133

Rendering a Partial View on button click in a div C# MVC 5

I have been following the answers on here but can't seem to get it to work. I think it's firing my function and calling my controller but it isn't rendering my partial view. Any help would be awesome.

Controller

public ActionResult Detail(int? id)
{
    if (id == null)
    {
       return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    User_Accounts user_accounts = db.User_Accounts.Find(id);
    if (user_accounts == null)
    {
        return HttpNotFound();
    }
    return PartialView("_Detail", user_accounts);
}

HTML

<h2>Index</h2>
<div class="container left">

    <div class="panel-default panelbox" style="position:static">
        @*<p>
            @Html.ActionLink("Create New", "Create")*@

        @using (Html.BeginForm("Index", "Users", FormMethod.Get))
        {
            <p>
                Type: @Html.DropDownList("userType", "All")
            </p>
            <p>
                Last Name: @Html.TextBox("SearchString")
            </p>
        }
    </div>
    <div class="panel panel-default left">
        <div class="panel-heading">
            <label style="text-align:center">
                User
            </label>
        </div>
        <div class="table-responsive">
            <table id="UserTable" class="table-bordered table leftPanel table-condensed">
                @foreach (var item in Model)
                {
                    <tr>
                        <td>
                            <button data-url='@Html.Action("Detail", "Users", new { id = item.user_id_IN })' id="js-reload-details">@Html.DisplayFor(modelItem => item.DisplayName)</button>
                            @*@Html.ActionLink(item.DisplayName, "Detail", new { id = item.user_id_IN }, new { onclick = "renderPartial();" })*@
                        </td>
                    </tr>
                }
            </table>
        </div>
    </div>
</div>

<div>
    <label>Details</label>
    <div id="detailsDiv"></div>
</div>

Script

<script>
    $('.js-reload-details').click(function (evt) {

        var $detailDiv = $('#detailsDiv'),
            url = $(this).data('url');

        $.get(url, function (data) {
            $detailsDiv.replaceWith(data);
        });
        });
</script>

Let me know if you need anything else.

Upvotes: 5

Views: 22773

Answers (3)

Dawood Awan
Dawood Awan

Reputation: 7328

The id of your button id="js-reload-details"

  1. Mistake this code is repeated in a foreach loop. which will cause multiple id's of the same name on your HTML page.

  2. Your click event is on : '.js-reload-details'. which is a class:

so make your code like this:

@foreach (var item in Model)
{
    <tr>
        <td>
            <button data-url='@Html.Action("Detail", "Users", new { id = item.user_id_IN })' class="js-reload-details">
                @Html.DisplayFor(modelItem => item.DisplayName)
            </button>
        </td>
    </tr>
}

One error I noticed in your jQuery is that you have $detailsDiv.replaceWith(data); It should be $detailDiv according to your code: var detailDiv = $('#detailsDiv'); instead of $detailsDiv

<script>
    $(document).ready(function(){
        $('.js-reload-details').click(function (evt) {

            evt.stopPropagation();
            var detailDiv = $('#detailsDiv');

            // TRY using the attr function: 
            var url = $(this).attr("data-url");

            $.get(url, function (data) {
                detailDiv.html(data);
            });
        });   
    });      
</script>

UPDATE:

<script>
    $(document).ready(function(){
        $('.js-reload-details').click(function (evt) {              
            evt.stopPropagation();
            var detailDiv = $('#detailsDiv');

            // TRY using the attr function: 
            var url = $(this).attr("data-url");

            $.get(url).success(function(result) {
                    detailDiv.html(result);
            });
    });
</script>

Upvotes: 2

user3559349
user3559349

Reputation:

You cant use data-url='@Html.Action("Detail", "Users", new { id = item.user_id_IN })' in your button to generate a url. @Html.Action() is a method which calls you controller. What would be happening is that for each item in your model you would be hitting the Detail method of UsersController (performance must of been awful if you had a lot of items :) ).

Since you appear to need only the one url (/Users/Detail) I suggest you just store the ID in data to minimize the html generated. As noted in the other answers you also need to use a class name for the button to prevent invalid html, and I also suggest using type="button" because the default (depending on the browser) may be "submit" (you don't have a form so does not matter in this case, but its good practice to get into). There is also no real need to use @Html.DisplayFor() unless your using a custom DisplayTemplate or have a [DisplayFormat] attribute on the property.

Change the html to

<button type="button" data-id="@item.user_id_IN" class="js-reload-details">@item.DisplayName</button>

and the script to

var url = '@Url.Action("Detail", "Users");
$('.js-reload-details').click(function() {
  $.get(url, { id: $(this).data('id') }, function (data) {
    $('#detailsDiv').html(data);
  });
});

Note you do not want to use replaceWith() in your case. .replaceWith() would replace the actual div <div id="detailsDiv"></div> with the html your method returned, so the next time a user clicked on this or any other button, the method would be called, but <div id="detailsDiv"></div> no longer exists and nothing would happen.

$('#detailsDiv').html('Hello world');

renders

<div id="detailsDiv">Hello world</div>

but

$('#detailsDiv').replaceWith('Hello world');

renders

Hello world

Upvotes: 5

Christos
Christos

Reputation: 53958

It's a good practice we use unique id's for our HTML elements. Since the following statement is going to be executed mulitple times

  <button data-url='@Html.Action("Detail", "Users", new { id = item.user_id_IN })' id="js-reload-details">@Html.DisplayFor(modelItem => item.DisplayName)</button>

You will have multiple buttons with the same id. Instead of doing so, you could use a class.

 <button data-url='@Html.Action("Detail", "Users", new { id = item.user_id_IN })' @class="js-reload-details">@Html.DisplayFor(modelItem => item.DisplayName)</button>

Then you have to correct your script:

// Now we bound the click event in all the elements that contain
// the .js-reload-details class
$('.js-reload-details').click(function (evt) {  

    var $detailDiv = $('#detailsDiv');

    // Here was your the error
    var url = $(this).attr("data-url");

    $.get(url, function (data) {
        $detailsDiv.replaceWith(data);
    });
});

Upvotes: 1

Related Questions