Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to render HTML with jQuery from an AJAX call

I have a select box with a list of books. The user can select a book and hit the submit button to view the chapters on a separate page.

However, when the user changes the select box, I would like a partial page refresh to display the past notes the user entered on the book, and allow the user to write a new note for that book. I do not want the review and creation of notes for a particular book done on the next page with the chapters, as it will clutter it up.

I'm using Python/Bottle on the backend and its SimpleTemplate engine for the front end.

Currently, when the select box is changed, an ajax call receives a Json string containing the book information and all the notes. This json string is then converted into a json object via jQuery.parseJson().

What I would like to be able to do is then loop over the notes and render a table with several cells and rows.

Would I have to do this in jQuery/js (instead of bottle/template framework) ? I assume so as I only want a partial refresh, not a full one.

I'm looking for a piece of code which can render a table with variable numbers of rows via jQuery/js from a json object that was retrieved with ajax.

<head>
    <title>Book Notes Application - Subjects</title>
    <script src="http://code.jquery.com/jquery-latest.min.js"
        type="text/javascript"></script>

    <script>
        $(document).ready(function(){
            $('#subject_id').change(function(){
                var subject_id = $(this).val();
                $.ajax({
                    url : "subject_ajax?subject_id=" + subject_id,
                    success : function(data) {
                        alert(data)

                        json = jQuery.parseJSON(data);
                    },
                    error : function() {
                        alert("Error");
                    }
                });
            })
        })

    </script>
</head>
<body>

    <!-- CHOOSE SUBJECT -->
    <FORM action="/books" id="choose_subject" name="choose_subject" method="POST">
        Choose a Subject:
        <select name="subject_id" id="subject_id">
            % for subject in subjects:
                <option value="{{subject.id}}">{{subject.name}}</option>
            % end
        </select><input type="submit" name="sub" value="Choose Subject"/>
        <BR />
    </FORM>
like image 406
Matthew Moisen Avatar asked Mar 23 '14 23:03

Matthew Moisen


People also ask

Can you use jQuery with AJAX?

What About jQuery and AJAX? jQuery provides several methods for AJAX functionality. With the jQuery AJAX methods, you can request text, HTML, XML, or JSON from a remote server using both HTTP Get and HTTP Post - And you can load the external data directly into the selected HTML elements of your web page!

How send AJAX response to HTML?

ajax({ url: 'test. html', dataType: 'html', success: function(response) { $('#testDiv'). html(response); } }); The code above will take all of the code you retrieved with your AJAX query and will output it into the testDiv.

How do I load HTML in AJAX?

load(URL,data,callback); The required URL parameter specifies the URL you wish to load. The optional data parameter specifies a set of querystring key/value pairs to send along with the request. The optional callback parameter is the name of a function to be executed after the load() method is completed.

Can you use AJAX on HTML file?

AJAX stands for Asynchronous JavaScript And XML. In a nutshell, it is the use of the XMLHttpRequest object to communicate with servers. It can send and receive information in various formats, including JSON, XML, HTML, and text files.


3 Answers

This greatly depends on how your JSON and HTML are formatted. But with a table somewhere like:

<table id="books">
  <tr>
    <th>Chapter</th>
    <th>Summary</th>
  </tr>
</table>

You could do something like:

$(function(){
    $('#choose_subject').submit(function () {
        var subject_id = $(this).val();
        $.getJSON("subject_ajax?subject_id=" + subject_id, function(data) {
            console.log(data);
            $.each(data.chapters, function (index, chapter) {
                $('#books').append('<tr><td>' + chapter.title + '</td><td>' + chapter.summary + '</td></tr>');
            })
        });
        return false;
    })
})

This supposes JSON like:

{
  "notes": [
    "Note 1",
    "Note 2"
  ],
  "chapters": [
    {
      "title": "First chapter",
      "summary": "Some content"
    },
    {
      "title": "Second chapter",
      "summary": "More content"
    }
  ]
}

Other notes:

  • If you use HTML 4 or earlier, keep all your tags in upper case. If you're using XHTML or HTML5, keep all your tags in lower case.
  • You don't need $(document).ready(function () {...}), with recent versions of jQuery $(function () {...} ) works the same and it's easier to read.
  • You can use $.get instead of $.json if you're only using the success state (as you are here). And if you're confident that the data you'll get is valid JSON, you can use getJSON instead of get. It will parse the JSON for you deliver it to you as a JavaScript object automatically.
  • It's usually more convenient to use console.log rather than alert when you're testing. Actually, it's usually a bad idea in general to ever use alert.
like image 120
eje211 Avatar answered Nov 08 '22 12:11

eje211


I'm not familiar with Python/Bottle or its SimpleTemplate engine, but you could consider generating the html for the table on the server side and returning it in the ajax response, rather than returning JSON.

var subject_id = $(this).val();
$.ajax('subject_ajax', {
    type: 'get',
    data: { subject_id: subject_id },
    dataType: 'html',
    success : function(html) {
        // Insert the html into the page here using ".html(html)"
        // or a similar method.
    },
    error: function() {
        alert("Error");
    }
});

When calling .ajax():

  1. The "type" setting defaults to "get", but I prefer to explicitly set it.
  2. Use the "data" setting for the ajax call to specify the URL parameter.
  3. Always specify the "dataType" setting.

I also recommend you perform the ajax call in an on-submit handler for the form, and add an on-change handler for the select that submits the form.

$(document).ready(function(){
    $('#subject_id').change(function() {
        $(this.form).submit();
    });

    $('#choose_subject').submit(function(event) {
        event.preventDefault();
        var subject_id = $('#subject_id').val();
        if (subject_id) {
            $.ajax(...);
        }
    });
});

This way your submit button should work in case it is clicked.

like image 37
John S Avatar answered Nov 08 '22 13:11

John S


There are a few things you need to look at:

1) Is your SimpleTemplate library included? 2) Have you compiled your template via compileTemplate()?

Once you know your library is included (check console for errors), pass your data returned to your success handler method, compile your template, that update whichever element you are trying to update.

I'm not sure that you want to update the same element that you're defining your template in.

$(document).ready(function(){
    $('#subject_id').change(function(){
        var subject_id = $(this).val();
        $.ajax({
            url : "subject_ajax?subject_id=" + subject_id,
            success : function(data) {

                var template_data = JSON.parse(data);
                var template = $('#subject_id').toString(); // reference to your template
                var precompiledTemplate = compileTemplate(template);
                var result = precompiledTemplate(template_data);
                $('#subject_id').append(result);

            },
            error : function() {
                alert("Error");
            }
        });
    })
})

You might also try moving your template out of the element you're trying to update like this:

<script type="text/template" id="subject-select-template">
% for subject in subjects:
    <option value="{{subject.id}}">{{subject.name}}</option>
% end
</script>

Then just create a blank select element like so:

<select id="select_id"></select>

Update references. Anyway, hope this is helpful. It should work but I can't test without your specific code ;)

Also, check out this demo example if you haven't yet: https://rawgithub.com/snoguchi/simple-template.js/master/test/test.html

like image 1
David Yerrington Avatar answered Nov 08 '22 12:11

David Yerrington