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.

Nikolay Kostov
  • 16,433
  • 23
  • 85
  • 123
Darkwingduck
  • 133
  • 1
  • 3
  • 12
  • 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 – Christos Feb 02 '15 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 – Darkwingduck Feb 02 '15 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? – Christos Feb 02 '15 at 20:37
  • I don't see any errors. – Darkwingduck Feb 02 '15 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. – Christos Feb 02 '15 at 20:46
  • when i try just url im getting Uncaught ReferenceError: url is not defined so i trued $(this).data('url'); and it says its undefined. I should add that I am quite new to this so I could have it all wrong lol – Darkwingduck Feb 02 '15 at 20:51
  • Actually I found where is your error. Please see my post in a few minutes and let me know. Thanks – Christos Feb 02 '15 at 20:58
  • Did you try by placing a break point in your server side code and see if action is actually getting hit? Also pass some id while sending the ajax call and also put your java script code in jquery ready function. – Imran Balouch Feb 02 '15 at 20:58

3 Answers3

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
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>
Dawood Awan
  • 7,051
  • 10
  • 56
  • 119
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);
    });
});
Christos
  • 53,228
  • 8
  • 76
  • 108
  • `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](http://jsperf.com/jquery-data-vs-attr/22)) –  Feb 03 '15 at 01:38