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.

8
  • 2
    Could you please remove this evt.preventDefault() and this evt.stopPropagation() and tell me if that solves your problem. It does make sense to me why you so need this. Thank you in advance Commented Feb 2, 2015 at 20:34
  • I dont know why I had that either to be honest, that was just in the example i was following. I removed it and it didn't seem to change anything. Thanks though Commented Feb 2, 2015 at 20:36
  • You welcome dude. One more question. If you open the console (Chrome developer tools - or your browser developer tools), do you see any errors there? Commented Feb 2, 2015 at 20:37
  • I don't see any errors. Commented Feb 2, 2015 at 20:42
  • ok, look what you can try. place a debugger before var $detailDiv, a statement debugger;. Then request your page and click on the element you expect to reload the details. The the execution will stop. Go to the console and write url and hit enter. Is this the correct url? One thing that seems strange to me is the fact that you don't even pass an id to your Detail action. Commented Feb 2, 2015 at 20:46

3 Answers 3

5

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
Sign up to request clarification or add additional context in comments.

Comments

2

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>

13 Comments

So in the console I can see all the data that should be loading. It pulls in the correct ID and all the correct data from the database but it's not rendering it to the screen.
Is the data returned from Controller in HTML?
Yes, i believe so. In the console it is in Html and it is coming from the controller.
<div id="detailsDiv"></div> If you inspect this element using Chrome do you see you HTML inside this DIV?
Nope its just <div id="detailsDiv"></div>
|
1

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);
    });
});

1 Comment

var url = $(this).data('url'); and var url = $(this).attr("data-url"); produce identical results (as will var url = $.data($(this), 'url'); which gives the best performance. Refer performance comparison)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.