Johnrad
Johnrad

Reputation: 2655

Div content clears after jquery updates it

I am currently generating some HTML in my jquery. The data is coming from a JSON file.

Here is my code creating said HTML:

$(document).ready(function () {
        $('#searchForm').submit(function () {
            var entry= $("#searchForm").val();

            $.ajax({
                type: 'POST',
                url: '@Url.Action("myMethod", "myController")',
                data: { 'entry': entry},
                success: function (result) {
                    var jsonData = jQuery.parseJSON(result);
                    buildHTML(jsonData);
                    debugger;     

                },
                error: function (result) {
                    debugger;
                }
            });
        });
    });

    function buildHTML(jsonData)
    {

        var content = ' ';

        $.each(jsonQC, function (i, item) {
           content += //html generation here
        });

        $('#myDiv').html(content);
    }

When I have the console open, the debugger stops the execution of my jquery. At the time the debugger line is hit, all of my html is displayed perfectly onto my view. When I let my code continue, all of the content is cleared from the page.

If it helps at all, here is my form code:

<form id="qcForm" action="">
    <div class="row">
    <div class="col-sm-4">
        <div class="input-group">
            <input id="searchForm" type="text" name="serverName" class="form-control" placeholder="Enter server name">
            <span class="input-group-btn">
                <button id="searchBtn" class="btn btn-default">Search</button>
            </span>
        </div>
    </div>
</div>

Upvotes: 0

Views: 81

Answers (3)

Eric Lease
Eric Lease

Reputation: 4194

In the submit event handler try event.preventDefault().

...
    $('#searchForm').submit(function (evt) {
        var entry;

        evt.preventDefault(); 
        entry = $("#searchForm").val();           

        $.ajax({
            type: 'POST',
            url: '@Url.Action("myMethod", "myController")',
            data: { 'entry': entry},
            success: function (result) {
                var jsonData = jQuery.parseJSON(result);
                buildHTML(jsonData);
                debugger;     

            },
            error: function (result) {
                debugger;
            }
        });
    });
...

Why this is happening

In addition to jQuery's docs on event.preventDefault and event.stopPropagation, check these out:

  1. Bubbling and capturing (javascript)
  2. event.preventDefault() vs. return false

You will see there are two things going on, default action and event bubbling.

Default action - The default action for the form's submit event is to perform an http post with the form data. You are catching the event on the client before it posts back, and starting an AJAX call to perform the work instead. But while that AJAX call is off doing its thing, the single threaded javascript engine is still within the context of the submit event handler. At that point you have the opportunity to prevent the default action. If you do not it will be "queued" to take place when the submit event handler completes. However, after the ajax request starts, but before the submit event handler completes, the ajax request completes. Therefore, it's promise handler is "queued" up to execute ASAP. When the submit event handler completes the success fires for the ajax request. Thus you can hit the debugger line(s) in its success handler. But immediately after that, the submit event's default behavior takes place, which causes a full refresh of the page. That is what you are seeing - your DOM immediately reset after the default behavior (full postback) completes. jQuery provides event.preventDefault() to offer cross-browser support to stop the default behavior.

Event Bubbling - If you have nested DOM elements, and each element in the chain handles the same event, the event will bubble up synchronously from the inner most element to the outer most element if event propagation is not stopped.

Consider this snippet...

<div onclick="outerDivClick()">
    <div onclick="innerDivClick()">
        <input onclick="inputClick()" />
    </div>
</div>

When clicking on the input the default behavior would be for, inputClick() to fire, then the event would bubble up to the inner div and innerDivClick() would fire, etc. This could go all the way up to the body if one of the event handlers along the way did not call event.stopPropagation() or return false;.


return false; GOTCHA from the SO answer linked above

Note that this behaviour differs from normal (non-jQuery) event handlers, in which, notably, return false does not stop the event from bubbling up.


Non-jQuery

I say "cross browser support" above due to legacy issues such as this, and to avoid the confusion that results from this. That being said, event.preventDefault and event.stopPropagation may be available to you in a plain js event handler.


One last thing, jQuery's event.stopImmediatePropagation is a useful variant if you want a specific handler to prevent propagation of the event to other handlers for the same DOM element.

Upvotes: 3

JuaRoAl
JuaRoAl

Reputation: 201

Probably you have to declare an empty var content before concatenate html to it.

function buildHTML(jsonData){

  var content = " "

  $.each(jsonQC, function (i, item) {
     content += //html generation here
  });

  $('#myDiv').html(content);
 }

Upvotes: 0

mjwunderlich
mjwunderlich

Reputation: 1035

You're using var content out of scope, and you're re-declaring it for each iteration of the each loop. Just declare var content = ''; right before your $.each loop:

function buildHTML(jsonData)
{
    var content = '';
    $.each(jsonQC, function (i, item) {
       content += //html generation here
    });

    $('#myDiv').html(content);
}

Upvotes: 0

Related Questions