NealR
NealR

Reputation: 10669

jQuery .append(html) command appending incorrectly

I am using a jQuery/Ajax call to append a partial view to a table. When the page loads, the partial view is created correctly. However, once the use attempts to append another item to the table, the formatting is incorrect despite the exact same partial view being used.

Here is the table. When this loads, the items are loaded onto the page correctly as the picture below illustrates:

     <table id="fixedRows">
     <thead>
        <tr>
           <th>State Code</th>
           <th>Agent ID</th>
           <th></th>
           <th></th>
        </tr>
    </thead>
    <tbody>    
    @foreach (var item in Model.BankListAgentId)
    {                    
        if (!String.IsNullOrWhiteSpace(item.AgentId) && item.FixedOrVariable.Equals("F"))
        {
            @Html.EditorFor(model => item, "FixedPartialView")                     
        }
    }
</tbody>
</table>
<br />
<a href="#" class="addFixed">Add Another</a>

enter image description here

Once you click the Add another link, this jQuery/Ajax call is activiated

<script type="text/javascript">
    $(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); }
            });
        });

    });


</script>

That jQuery calls this method from the controller

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

Which calls this partial view EDIT(a couple people noticed the id tag missing from the <tr>, this was just a copy/paste error for this post, the actual code has the id tag)

    @model Monet.Models.BankListAgentId

@{
    Layout = null;
}
    @using (Html.BeginCollectionItem("BankListAgentId"))
    {
        <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="#" class="deleteRow">delete</a>
            </td>
            @*<td><a href="#" onclick="$('#[email protected]').parent().remove();" style="float:right;">Delete</a></td>*@
        </tr>
    }

This is the same partial view that is called when the page first loads, which part of why I'm confused that the end result after hitting the Add another link turns out looking like this

enter image description here

EDIT

If you hit the Add another link twice, this is the result

enter image description here

EDIT

I've tried the following jQuery sucess commands with no luck

success: function (html) { $("#fixedRows > tbody:last").append(html); }
success: function (html) { $("#fixedRows tr:last").after(html); }
success: function (html) { $("#fixedRows  > tbody").append(html); }

Here is the HTML that is rendered after the Add another link is clicked. I included the opening <form> tag for the form below it to show that the new rows are nowhere to be found.

<form action="/BankListMaster/Edit/11" method="post">        
    <fieldset>
        <legend>Stat(s) Fixed</legend>
        <table id="fixedRows">
            <tr>
                <th>State Code</th>
                <th>Agent ID</th>
                <th></th>
                <th></th>
            </tr>

            <tr id="item-1164998320">
                <td>
                    <select id="item_StateCode" name="item.StateCode"><option value="">HI</option>
                        <option>AL</option>
                        ..
                        <option>WY</option>
                    </select>
                </td>
                <td>
                    <input class="text-box single-line" id="item_AgentId" name="item.AgentId" type="text" value="1164998320" />
                    <span class="field-validation-valid" data-valmsg-for="item.AgentId" data-valmsg-replace="true"></span>
                </td>
                <td>
                    <a href="#" class="deleteRow">delete</a>
                </td>
            </tr>    
            <tr id="item-1164998219">
                <td>
                    <select id="item_StateCode" name="item.StateCode">
                        <option value="">HI</option>
                        <option>AL</option>
                        ..
                        <option>WY</option>
                    </select>
                </td>
                <td>
                    <input class="text-box single-line" id="item_AgentId" name="item.AgentId" type="text" value="1164998219" />
                    <span class="field-validation-valid" data-valmsg-for="item.AgentId" data-valmsg-replace="true"></span>
                </td>
                <td>
                    <a href="#" class="deleteRow">delete</a>
                </td>
            </tr>    
            <tr id="item-0352926603">
                <td>
                    <select id="item_StateCode" name="item.StateCode">
                        <option value="">GA</option>
                        <option>AL</option>
                        ..
                        <option>WY</option>
                    </select>
                </td>
                <td>
                    <input class="text-box single-line" id="item_AgentId" name="item.AgentId" type="text" value="0352926603" />
                    <span class="field-validation-valid" data-valmsg-for="item.AgentId" data-valmsg-replace="true"></span>
                </td>
                <td>
                    <a href="#" class="deleteRow">delete</a>
                </td>
            </tr>            
        </table>
        <br />
        <a href="#" class="addFixed">Add Another</a>
    </fieldset>
</form>     
<a href="#" class="addFixed">Add Another</a>
<form action="/BankListMaster/Edit/11" method="post">   

EDIT

Here is a screen shot of the table in Chrome's debugger after the Add Another link is clicked. As you can see, the data pulled from the table is loaded properly in respective <tr> tags, however the empty row (which is sent via the same partial view as the rest) doesn't have any of the same table elements. The screen shot below that shows Response, however, which does include the <tr> tags

enter image description here
enter image description here

EDIT

I put a console.log(html) line in the success Ajax function so it now reads

            success: function (html) {
                console.log(html);
                $("#fixedRows > tbody").append(html);
            }

Here is the console output (state edited for readability)

<input type="hidden" name="BankListAgentId.index" autocomplete="off" value="3f7e0a92-8f20-4350-a188-0725919f9558" />
        <tr>
            <td>
                <select id="BankListAgentId_3f7e0a92-8f20-4350-a188-0725919f9558__StateCode" name="BankListAgentId[3f7e0a92-8f20-4350-a188-0725919f9558].StateCode">
                    <option>AL</option>
                    ..
                    <option>WY</option>
                </select>
            </td>
            <td>
                <input class="text-box single-line" id="BankListAgentId_3f7e0a92-8f20-4350-a188-0725919f9558__AgentId" name="BankListAgentId[3f7e0a92-8f20-4350-a188-0725919f9558].AgentId" type="text" value="" />                 
            </td>
            <td>
                <a href="javascript:void(0)" class="deleteRow">delete</a>
            </td>               
        </tr>

Upvotes: 6

Views: 3912

Answers (2)

NealR
NealR

Reputation: 10669

What a complete nightmare...

First off, the HTML that was being returned as viewable in Chrome's debugger was fine, however when I clicked on "View Source" for the page, I could not see anything but what was originally loaded. After finding this post, I found that this is normal. I then used this Chrome add-on to finally see that the <tr> and <td> tags were being stripped out. By simply adding an opening and closing tag to the append statement, I got the returned items to append to the table.

    $(".addFixed").click(function () {
        $.ajax({
            url: '@Url.Action("BlankFixedRow", "BankListMaster")',
            dataType: 'html',
            cache: false,
            success: function (html) {
                $("#fixedRows > tbody").append('<tr>' + html + '</tr>');
            }
        });
    });

Upvotes: 3

user1159653
user1159653

Reputation:

I see a few things here. You're referencing <tbody> in some of your code but I don't see it anywhere in the page. So first I would suggest using <thead> and <tbody>. In your partial view I see <tr "[email protected]"> which should have an id.

You should also remove the onclick handler and the delete button and put that in with the rest of your JavaScript. Set a class on your delete links instead.

For links that don't need urls and are only used for attaching JavaScript handlers, I recommend using href="javascript:void(0)" as this would prevent the browser from doing anything special with href="#" so then you'll be able to remove the calls to preventDefault().

As to the source of your problem, $("#fixedRows tbody").append(html) is the code you want so no need to try after(). It looks like your html is getting stripped. Try setting the dataType attribute in the $.ajax() call to html.

Upvotes: 1

Related Questions