Reputation: 1927
I sent an Ajax request to server to get some filtered data and here is a sample I receive from server:
(3) [{…}, {…}, {…}]
0: {id: 1, title: "12 Rue Longueil", slug: "12-rue-longueil", latitude: null, longitude: null, …}
1: {id: 2, title: "15 Rue Sherbrooke LM", slug: "15-rue-sherbrooke-lm", latitude: null, longitude: null, …}
2: {id: 3, title: "Cycle Neron", slug: "cycle-neron", latitude: "-73.5987000000000000", longitude: "45.4799000000000000", …}
length: 3
__proto__: Array(0)
above data is logged from console.
I want to display these data in HTMl tags within cards below.
but for that I need to use that received data and create children using JavaScript e.g. document.createElement('DIV')
. and then place these data.
$(document).on('submit', "#filterform", function (e) {
e.preventDefault();
$.ajax({
type: 'GET',
url: "{% url 'listing:search' %}",
data: {
listing_for: $('#listing_for').val(),
// cutted
},
success: function (response) {
const listings = eval(response);
const content = document.getElementById('content');
for (let i = 0; i < listings.length; i++) {
const div = document.createElement('div');
div.className = 'listing mgb-1';
div.innerHTML = data[i].title;
content.appendChild(div);
// have to create, add lots of divs and classes
}
}
})
})
I was wondering if there is a way to sent Ajax request data as template variable? Or do I have to hardcode all HTML tags using Javascript?
Edit: Edited content based on first answer creating a separate HTML.
def search(request):
...
lst = list()
for listing in queryset:
ser = ListingSerializer(listing)
lst.append(ser.data)
return render(request, 'listing/newHtmlFile.html', {'listings': json.dumps(lst)})
separate HTML:
{% for list in listings %}
<div class="jumbotron">
<h1>{{ list.title }}</h1>
</div>
{% endfor %}
and ajax request:
success: function (response) {
document.querySelector('#content').insertAdjacentHTML('beforeend', response);
}
Upvotes: 1
Views: 1109
Reputation: 2272
Yes, you can. Basically the idea is to make a separate HTML file that's going to be rendered by the view that handles the AJAX request. Then, you can use JavaScript and the insertAdjacentHTML()
function to insert it in your original HTML file.
Take a look at this example:
view:
def ajax_handler(request):
# ... logic
return render(request, 'newHtmlFile.html', {'your_context': data})
Original HTML file
<div id='container'>
</div>
newHtmlFile.html
<p>{{ your_context }}</p>
JavaScript part (in this example I use Vanilla, not JQuery)
let ajax = new XMLHttpRequest();
ajax.onreadystatechange = function(){
if (this.readyState === 4){
if (this.status === 200){
document.querySelector('#container').insertAdjacentHTML('beforeend', this.responseText);
}
}
}
ajax.open('GET', '/ajax-handler-url', true);
ajax.send();
If you are interested to know how this works, we can break it down as follows:
render()
method and you pass that data as the context data to a templaterender()
method what actually does is to (let me be redundant here) render a HTML file (combining the HTML itself with the context data you passed) and return a HTTPResponse
object containing a rendered text.$.ajax()
function that made the request.insertAdjacentHTML()
function to append that rendered text to the desired element (in the example above, the #container
div).Upvotes: 1
Reputation: 27311
A quick, and possibly "dirty", way of doing it is to use the backtick strings in javascript:
success: function (r) {
const listings = JSON.parse(r); // with the correct headers from django, this should't be needed.
listings.forEach(e => $('#content').append(`
<div class="listing mgb-1">${e.title}</div>
`));
}
You should return your data from django with the appropriate headers so you automatically get json and don't need to eval(response)
.
Upvotes: 1