6

I am currently using an Ajax call on my ASP MVC3 view to append a new list item to the page. The view makes the Ajax call, which calls a controller ViewResult action, which returns the partial view. The Ajax is then set to call the .append(html) method on the <div> element the call originated from.

The problem is that instead of appending the new row, the entire view goes away and only the partial is displayed.

Here is the code in the view. This view uses a view model with a list object of a separate model. This portion of the code calls the partial view to display each of the items in the list object.

@model Monet.ViewModel.BankListViewModel
@using (Html.BeginForm())
{
    <fieldset>
        <legend>Stat(s) Fixed</legend>
        <table>
        <th>State Code</th>
        <th>Agent ID</th>
        <th></th>
            <div class="fixedRows">
                @foreach(var item in Model.Fixed)
                {
                    if (!String.IsNullOrWhiteSpace(item.AgentId))
                    {

                            @Html.Partial("FixedPartialView", item) 

                    }      
                }
            </div>
        </table>
        <br />
        @Html.ActionLink("Add another", "BlankFixedRow", null, new { id = "addFixed"})
    </fieldset>
}

Here is the addFixed Ajax call

$("#addFixed").click(function () {
    $.ajax({
        url: this.href,
        cache: false,
        success: function (html) { $("#fixedRows").append(html); }
    });
    return false;
});

and this is the ViewResult controller action that the Ajax calls

    public ViewResult BlankFixedRow()
    {
        SelectList tmpList = new SelectList(new[] { "AL", "AK", "AS", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FM", "FL", "GA", "GU", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MH", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NA", "NM", "NY", "NC", "ND", "MP", "OH", "OK", "OR", "PW", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "US", "VT", "VI", "VA", "WA", "WV", "WI", "WY" });
        ViewBag.StateCodeList = tmpList;

        return View("FixedPartialView", new BankListAgentId());
    }

Finally, this is the partial view.

@model Monet.Models.BankListAgentId


@using (Html.BeginCollectionItem("Fixed"))
{
    <tr id="[email protected]">
        <td>
            @Html.DropDownListFor(model => model.StateCode,
                (SelectList)ViewBag.StateCodeList, Model.StateCode)
        </td>
        <td>
            @Html.EditorFor(model => model.AgentId)
            @Html.ValidationMessageFor(model => model.AgentId)
        </td>
        <td>
        <a href="#" onclick="$('#[email protected]').parent().remove();" style="float:right;">Delete</a></td>
    </tr>
}

When the Add another link is selected the page goes from looking like this

enter image description here

to this

enter image description here

Per comments below here is the HTML for the page:

<input type="hidden" name="Fixed.index" autocomplete="off" value="6dd1b028-14f7-4400-95d1-a803c2521b68" />
        <tr id="item-">
            <td>
                <select id="Fixed_6dd1b028-14f7-4400-95d1-a803c2521b68__StateCode" name="Fixed[6dd1b028-14f7-4400-95d1-a803c2521b68].StateCode"><option>AL</option>
<option>AK</option>
<option>AS</option>
<option>AZ</option>

.
.
. <-removed list of all 50 states for clarity
</select>
            </td>
            <td>
                <input class="text-box single-line" id="Fixed_6dd1b028-14f7-4400-95d1-a803c2521b68__AgentId" name="Fixed[6dd1b028-14f7-4400-95d1-a803c2521b68].AgentId" type="text" value="" />

            </td>
            <td>
                <a href="#" class="deleteRow">delete</a>
            </td>

        </tr>
                    </section>

EDIT

After reading the comments below I changed the table tag to <table id="fixedRows">, however, this returned the same result. I then changed the success attribute of the Ajax call to include some basic HTML like so

success: function (html) { $("#fixedRows").append("<tr><td>New</td></tr>"); }

but again, got the same result. After setting a breakpoint both in Visual Studio and Chrome's debugger, I was able to see that the Ajax is never being called. Instead the call to the controller action is made, and the partial view is loaded on it's own, instead of being appended to <table id="fixedRows">.

Still working of getting around this, however, if anyone has any ideas. Thx!

7
  • Is there a reason you want to use Ajax to do the partial call? When you use Ajax you have to remember the state of the previous page in order for Ajax to redisplay the page Commented Apr 3, 2013 at 18:12
  • 1
    I'm following this blog post: blog.stevensanderson.com/2010/01/28/… Commented Apr 3, 2013 at 18:14
  • Can you inspect the rendered markup of the table after clicking 'Add another' and post that? Commented Apr 3, 2013 at 18:29
  • 1
    probably doesn't solve your problem but <div class="fixedRows"> doesn't match your selector $("#fixedRows").append(html) Commented Apr 3, 2013 at 18:41
  • 1
    Good Question you helped me a lot thanks NealR Commented Mar 10, 2014 at 9:06

4 Answers 4

2

So the reason this was happening wound up being pretty simple. Due to the ActionLink that was being used, the controller action would fire before the jQuery. This was causing the partial view to wipe out the entire Edit view. By binding the jQuery to a hyperlink within a $(document).ready block, the jQuery functioned like normal. Below is the tag and the updated jQuery

<a href="#" class="addFixed">Add Another</a>

jQuery:

$(document).ready(function () {

    $(".addFixed").click(function () {
        //alert('test');
        event.preventDefault();        
        $.ajax({
            url: '@Url.Action("BlankFixedRow", "BankListMaster")',
            cache: false,
            success: function (html) { $("#fixedRows").append(html); }
        });
    });

    $("#addVariable").click(function () {
        event.preventDefault();
        $.ajax({
            url: '@Url.Action("BlankFixedRow", "BankListMaster")',
            cache: false,
            success: function (html) { $("#variableRows").append(html); }
        });
    });

});
Sign up to request clarification or add additional context in comments.

Comments

0

The only way this could occur with the code you have is if it's not replacing the page content with that simple bit of HTML, but rather directly loading that action in the browser tab. Which your action link will do by default.

  1. Make sure that your click handler for that "Add another" link employs event.preventDefault() or simply returns false; If you don't prevent the default action of the link, you AJAX code will do it's thing, and then the browser will load the link like normal, making it look like it didn't work.

  2. Make sure there's no JavaScript errors on the page. If the JS stops working, then the default behavior, again, will take over and you get the result you see.

9 Comments

Regarding item 1: the current jQuery does have return false; specified at the end of the handler. Regarding item 2: This is the only jQuery/Javascript/Ajax code on the page. Just to make sure, however, I ran it step by step using Chrome's debugger and saw no errors.
I also tried replacing the success attribute with some basic html like so: success: function (html) { $("#fixedRows").append("<tr><td>New</td></tr>");, but I received the same results (partial view replacing the previous page). Could I be using the @Html.ActionLink incorrectly?
I don't know you jquery version but "success" is deprecated in 1.8, use ".done(function(html){})". Put a chrome debugger breakpoint in this function...
Just did that and found out the Ajax isn't even getting called.
It's not an issue of using @Html.ActionLink incorrectly. It's just a link. The fact that you received the same results even after explicitly appending different HTML confirms that it's still just loading the link, though, and not handling it via AJAX. Try using event.preventDefault() which is a little more explicit than relying on a return value of false.
|
0

I think that your usage of divs inside your <table> tags is confusing jQuery.append.

Try the following instead:

<fieldset>
    <legend>Stat(s) Fixed</legend>
    <table id="fixedRows">
        <tr>
            <th>State Code</th>
            <th>Agent ID</th>
        </tr>
        @foreach(var item in Model.Fixed)
        {
            if (!String.IsNullOrWhiteSpace(item.AgentId))
            {
                @Html.Partial("FixedPartialView", item) 
            }      
        }
    </table>
    <br />
    @Html.ActionLink("Add another", "BlankFixedRow", null, new { id = "addFixed"})
</fieldset>

Note, also, that I have used id="fixedRows" instead of class="fixedRows" as this is what you're specifying in your jQuery.

Compare:

1 Comment

Interesting.. I changed the code in my view to look exactly like yours in the answer. I got the same results, so I tried copying your success attribute like so: success: function (html) { $("#fixedRows").append("<tr><td>New</td></tr>");, thinking I would at least be able to see a new <tr> element added to the page. Instead, I got the exact same results as before - the entire view gone and replaced with just the partial.
0

I try an avoid doing AJAX calls on partial views. AJAX requires you remember the state of the last page in order to redisplay the information. That being said you can go back to the controller and call the partial view and just have the server call display the partial in tandem with your view:

 @Html.Partial("FixedPartialView", new BankListAgentId(){/*Construct the View Model Here here. assign the properties to your view model */  AgentId = /*however your creating this*/})

I do not think AJAX is the way to go with this problem.

2 Comments

What do you mean by construct the object here? Currently the new HTML from the partial is sent via the controller and appended to the table.
Edited my post for more clarity.

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.