Render template into Symfony2 with ajax - ajax

I have a action in my controller for the index route
routing.yml
index:
pattern: /index
defaults: { _controller:AcmeDemoBundle:Default:index }
Controller for this path
public function indexAction()
{
return $this->render('AcmeDemoBundle:Plugin:index.html.twig');
}
And the index.html.twig template
{% extends'::base.html.twig' %}
{% block stylesheets %}
{% stylesheets filter='cssrewrite' output='css/*.css'
'bundles/acmedemo/css/*' %}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" />
{% endstylesheets %}
{% endblock stylesheets %}
{% block body %}
<br>
<div class="container">
<div class="wp_attachment_holder">
<div class="imgedit-response" id="imgedit-response-8"></div>
<div class="wp_attachment_image" id="media-head-8">
<p id="thumbnail-head-8"><img class="thumbnail" src="http://localhost/wordpress/wp-content/uploads/2014/06/121-1024x583.jpeg" style="max-width:100%" alt=""></p>
<p><a class="btn btn-sm btn-default" id="edik-wp-extended-edit">Редактировать</a> <span class="spinner"></span></p>
</div>
<div style="display:none" class="image-editor" id="image-editor-8">
</div>
</div>
<div id="output"></div>
<img class="thumbnail" data-attach-id="8" data-src="http://localhost/wordpress/wp-content/uploads/2014/06/121-1024x583.jpeg" style="max-width:100%" alt="">
<script>
$('#edik-wp-extended-edit').click(function() {
window.location= Routing.generate('ajax');
// $('#output').load('/ajax/index');
});
</script>
</div>
{% endblock %}`
When the button Редактировать is clicked i want to load another template with ajax.
another.html.twig
<div>Hello</div>
routing.yml
ajax:
pattern: /ajax/index
defaults: { _controller :AcmeDemoBundle:Default:ajax }
options:
expose: true
Controller for this path
public function ajaxAction()
{
$template = $this->renderView('AcmeDemoBundle:Plugin:another.html.twig');
return new Response($template);
}
But when i click the button my uri will be /ajax/index. What i want is that it stays by /index and the template will be rendered into my index template
What am i doing wrong?
Thanks.

First, your ajaxAction() should be a bit different as far as I know.
For me this works:
$template = $this->forward('AcmeDemoBundle:Plugin:another.html.twig')->getContent();
$json = json_encode($template);
$response = new Response($json, 200);
$response->headers->set('Content-Type', 'application/json');
return $response;
The forward() function renders the template and returns the rendered HTML code.
Your JavaScript file should look like this:
$.ajax({
type: "POST",
dataType: 'json',
url: Routing.generate('ajax'),
async: false //you won't need that if nothing in your following code is dependend of the result
})
.done(function(response){
template = response;
$('#your_div').html(template.html); //Change the html of the div with the id = "your_div"
})
.fail(function(jqXHR, textStatus, errorThrown){
alert('Error : ' + errorThrown);
});
You make an AJAX call to the your ajaxAction, which will return the HTML of the template you want to be rendered.
After that you just need to add a <div id="your_div"></div> at the position you want the template to be rendered. This workes perfectly for me.
To mention is that you need to break down the ajax template to just the code that should be shown.

Please try generate ajax route like this
window.location= '{{ path("ajax") }}';
Added:
For make ajax request change windows.location to ajax request
$( "#output" ).load( '{{ path("ajax") }}', function() {
alert('Load done');
});
Added explanation of use:
js code will work only if you put it on Twig template. If you put it to js file it will not work.
In case of original questions.
<div id="output"></div>
<img class="thumbnail" data-attach-id="8" data-src="http://localhost/wordpress/wp-content/uploads/2014/06/121-1024x583.jpeg" style="max-width:100%" alt="">
<script>
$('#edik-wp-extended-edit').click(function() {
$( "#output" ).load('{{ path("ajax") }}');
});
</script>
You can use something like FOSJsRoutingBundle to proper use SF2 routing in js

Related

Post form using AJAX in Django

I'm trying to POST form in Django using Ajax. I've already done this way before but now i cant find whats wrong with my code. When submitting the form, ajax POST's to wrong URL even though i've provided the right URL. I want to post to "/upload/videoUpload/" but it keeps on posting to "/upload".Below is the code.
HTML:
<form id="videouploadForm" method="POST" >
{% csrf_token %}
<input type="text" id="vidlc" name="video" value="submit" style="display: none" >
<input type="submit" id="sBm120" style="display: none"/>
</form>
AJAX:
<script>
$('#sBm120').trigger('click');
$(document).ready(function() {
$("#videouploadForm").submit(function(event){
event.preventDefault();
$.ajax({
method:"POST",
url:"/upload/videoUpload/",
data: {
'video': $('#vidlc').val(),
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val()
},
success: function(data){
if (data.status){
alert(data.status);
var result = " <video poster='{% static 'images/single-video.png' %}' style='height:30vh' controls='controls' width='100%' height='30%'><source src='http://gateway.ipfs.io/ipfs/"+data.filehash+"' type='video/mp4; codecs='avc1.42E01E, mp4a.40.2'></video>";
document.getElementById("upv").innerHTML=result;
}
}
});
return false; //<---- move it here
});
});
</script>
URLS.py:
path('upload/videoUpload/', uploadVid, name="uploadVideo"),
have you tried to use Django url template tags?
url:"/upload/videoUpload/", to
url:" '{% url " uploadVideo" %} ",
Hope it works!
Sorry if you dont see properly, writing from my phone :)

Refresh page without reload. Wagtail

Where can i put ajax get data code in Wagtail? I have following page model:
class ScreencastPage(Page):
content_panels = Page.content_panels + [
InlinePanel(
'groupstage_screencast_relationship', label="Choose Teams",
panels=None, max_num=2),
]
parent_page_types = ['home.HomePage']
def matches(self):
matches = [
n.match for n in self.groupstage_screencast_relationship.all()
]
return matches
And my template:
{% for spiel in page.matches %}
{% if forloop.first == forloop.last %}
<div id="fullscreen">
<ul class="ulup">
<li class="logo_bg first_team">{% image spiel.team_1.team_logo width-400 class="logo" %}<p>{{spiel.team_1.title}}</p></li>
<li class="first_team_score">{{ spiel.team_1_total_score }}</li>
<li class="colons">:</li>
<li class="second_team_score">{{ spiel.team_2_total_score }}</li>
<li class="logo_bg second_team">{% image spiel.team_2.team_logo width-400 class="logo" %}<p>{{spiel.team_2.title}}</p></li>
</ul>
</div>
{% endif %}
{% endfor %}
I started writing js. Just exaple:
$(document).ready(function() {
setInterval(function(){
$.ajax({
type: "GET",
url: {% pageurl page %},
data: {},
success: function(data) {
console.log(data);
$(".first_team_score").contents()[0].textContent = data.team_1_total_score;
$(".second_team_score").contents()[0].textContent = data.team_2_total_score;
}
})
}, 10000);
});
The idea is that the page will automatically update the value of <li class="first_team_score">{{ spiel.team_1_total_score }}</li> and <li class="second_team_score">{{ spiel.team_2_total_score }}</li> without reloading the page.
I found here great example, but they using view.py
We also need to write a new view.py or have wagtail some method for that?
UPDATE
Thanks #Ben-Dickinson from wagtail slack community. He shared a link to the documentation where it is indicated how it's possible to solve such a problem.
I have here another problem. How to convert matches to json?
To catch ajax requests we can use the Page serve() method and use if request.is_ajax():. So I did following inside my ScreencastPage(Page):
def serve(self, request):
if request.is_ajax():
result = [
{
'team_1_name': match.team_1.title,
'team_1_score': match.team_1_total_score,
'team_2_name': match.team_2.title,
'team_2_score': match.team_2_total_score,
}
for match in self.matches()
]
json_output = json.dumps(result)
return HttpResponse(json_output)
else:
return super(ScreencastPage, self).serve(request)
This code from above was the result of help from #gasman, this topic you can find here Converting value to json inside serve method
The final result of the HTML/JS code is:
<div id="match1">
<ul class="ulup">
<li class="logo_bg first_team">{% image spiel.team_1.team_logo width-400 class="logo" %}<p>{{spiel.team_1.title}}</p></li>
<li class="first_team_score">{{ spiel.team_1_total_score }}</li>
<li class="colons">:</li>
<li class="second_team_score">{{ spiel.team_2_total_score }}</li>
<li class="logo_bg second_team">{% image spiel.team_2.team_logo width-400 class="logo" %}<p>{{spiel.team_2.title}}</p></li>
</ul>
</div>
JS:
$(document).ready(function() {
setInterval(function(){
$.ajax({
type: "GET",
url: {% pageurl page %},
dataType: 'json',
success: function(data) {
$("#match1 .first_team").contents()[0].textContent = data[0]["team_1_name"];
$(".first_team_score").contents()[0].textContent = data[0]["team_1_score"];
$("#match1 .second_team").contents()[0].textContent = data[0]["team_2_name"];
$(".second_team_score").contents()[0].textContent = data[0]["team_2_score"];
}
})
}, 10000);
});
data[0] is becoz my data returns database of two matches and i need only first one

Django - reload div upon form submit

I am trying to refresh a certain div in a django application when a form is submitted.
index.html
<div class="col-md-8" id="notesColumn">
{% crispy note_form %}
{% include 'item/item_notes.html' %}
</div>
item_notes.html
<div class="panel-group panel-group-simple m-b-0" id="notesList" aria-multiselectable="true" role="tablist">
{% for note in object.itemnote_set.all reversed %}
<div class="panel">
<div class="panel-heading" id="noteHeading{{ forloop.counter }}" role="tab">
<a class="panel-title collapsed" data-parent="#notesList"
data-toggle="collapse" href="#noteCollapse{{ forloop.counter }}"
aria-controls="noteCollapse{{ forloop.counter }}" aria-expanded="false">
<span class="tag tag-default">{{ note.owner.first_name }}</span>
{{ note.get_action_display|upper }}
<small class="panel-actions">{{ note.date_added }}</small>
</a>
</div>
<div class="panel-collapse collapse" id="noteCollapse{{ forloop.counter }}"
aria-labelledby="noteHeading{{ forloop.counter }}" role="tabpanel" aria-expanded="false"
style="height: 0px;">
<div class="panel-body">
{{ note.content }}
</div>
</div>
</div>
{% endfor %}
</div>
app.js (included in index.html)
$(document).ready(function () {
$("#notesTab form").submit(function(event){
event.preventDefault();
$('#notesList').remove();
$.ajax({
url: "{% url item_notes %}",
success: function(data){
$('#notesColumn').html('data');
}
})
})
views.py
def item_notes(request):
return render_to_response(request, 'candidate/candidate_notes.html')
urls.py
url(r'item/profile/(?P<pk>[0-9]+)/$', views.ItemProfile.as_view(), name='item_profile'),
url(r'item/notes', views.item_notes, name='item_notes'),
The error I get from chrome is:
http://127.0.0.1:8000/crm/item/profile/45/%7B%%20url%20item_notes%20%%7D
Failed to load resource: the server responded with a status of 404 (Not Found)
You can't use Django template tags in your external JS file - Django does not parse that file, which is why you can see the literal tag being appended to your Ajax URL.
You will need to set that value as a global JS var inside an inline script in your template itself.
First, try to use an absolute URL to see, if it's the URL that causes the error:
$.ajax({
url: "item/notes",
success: function(data){
$('#notesColumn').html('data');
}
})
Second, why do you GET the notes URL? Aren't you using 'item_profile' for that? In that case, try to GET that URL:
$.ajax({
url: "item/profile/" + "{{ object.pk }}",
success: function(data){
$('#notesColumn').html('data');
}
})
Third, check you JS code, you are missing a closing bracket on $("#notesTab form").submit.
Fourth, try to escape the URL. I am not sure which method to use in JS, but I had that problem multiple times where it broke because of unescaped code.
These are just some tips of the top of my head. Hope that helps.

Can't get all comments to reload without page refresh after comment submitted thourgh ajax

I have been trying to come up with a scheme where the comments sections refreshes in a template when a user posts comments with the comment that was just posted being included. The page must not be refreshed.
Sorry for indentation.
template -
{% extends "home/header.html" %}
{% block content %}
{% if request.user.is_authenticated %}
<form>
{% csrf_token %}
<p>Comment: </p><input type="text" name="fname" id="posted_comment">
<input type="hidden" class='meme_char_id' meme_char_id={{meme.meme_char_id}}>
<input type="submit" id ="btnSubmit" name="submit" value="Post">
</form>
<!-- displaying comments here -->
<div class="box" id="comments_div">
<h3 class="h4">{{comment_count}} comments </h4>
<ul class="list-group">
{% for comment in all_comments %}
<h5>{{ comment.commentby.username }} : </h5>
<li class="list-group-item list-group-item-success">{{ comment.comment_text }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endblock %}
Now, my JS file is -
$(document).ready(function() {
$('#btnSubmit').click(function(e) {
e.preventDefault();
var data = new FormData();
var comment = $('#posted_comment').val()
var meme_char_id = $(".meme_char_id").attr('meme_char_id')
data.append('comment', comment);
data.append('meme_char_id', meme_char_id);
$.ajax({
type: 'POST',
url: '<mydomain>/comment/',
data: data,
processData: false,
contentType: false,
success: function(reply) {
$(".comments_div").html(reply)
}
})
});
});
And finally my view is -
def comment(request):
if request.is_ajax():
comment = request.POST['comment']
meme_char_id = request.POST['meme_char_id']
this_meme = Memes.objects.get(meme_char_id=meme_char_id)
print "comment - ", comment, " meme_char_id - ", meme_char_id
new_comment = Comments(comment_text=comment, meme_id=this_meme.meme_id, commentby_id=request.user.id)
new_comment.save()
all_comments = Comments.objects.filter(meme_id=this_meme.meme_id).order_by('-created_at').values()
return HttpResponse(all_comments, content_type='application/json')
else:
raise Http404
Couple questions -
I want to return an Comments query set through ajax(don't see a point in jsonifying it, if I can just send the query set to the template.)
The queryset I am returning to template isn't picked up by the comments_div in the view.
I am a rookie so please explain step by step what I am doing wrong. Thanks.
You are sending back a JSON in a response and doing$(".comments_div").html(reply). You must be sending back a template rendered with all_comments as response on successful comment. Also, a queryset is not JSON serializable as far as I understand.

Django, submiting a form via AJAX

I have seen answers (here and here) for similar questions, but none of them work in my case. I have a simple form in a template, I am using bootstrap for rendering.
Once I submit the form, the response is rendered directly in the browser. When I return to the previous page (with the browser's button) then the success part of the AJAX call is executed.
forms.py
class QueryForm(forms.Form):
query = forms.CharField(label='Discover something', max_length=256)
views.py
def query_view(request, id):
if request.method == 'POST':
# Just for testing, send True
response_data = {
'result': True
}
return HttpResponse(json.dumps(response_data), content_type="application/json")
else:
try:
# Create a form and send it to the template
query_form = QueryForm()
return render(request, 'query_template.html', {'query_form': query_form})
except ObjectDoesNotExist:
return render(request, 'error.html')
urls.py
urlpatterns = [
url(r'^query', views.query_view, name='query_view'),
url(r'^', views.home, name='home'),
]
query_template.html
{% extends 'base.html' %}
{% load static %}
{% load bootstrap3 %}
{% block content %}
{# Display a form #}
<form method="post" class="form">
{% csrf_token %}
{% bootstrap_form query_form %}
{% buttons %}
<button class="btn btn-primary" id="query-button">
{% bootstrap_icon "star" %} Submit
</button>
{% endbuttons %}
</form>
<ul id="result"></ul>
<script src="{% static 'scripts/main.js' %}"></script>
{% endblock %}
main.js
$('#query-button').click(function (event) {
$.ajax({
url: "/query/",
type: "POST",
data: {},
cache: false,
// handle a successful response
success: function (json) {
console.log(json); // log the returned json to the console
$("#result").html("<li>" + json.result + "</li>");
console.log("success"); // another sanity check
},
// handle a non-successful response
error: function (xhr, errmsg, err) {
console.log(xhr.status + ": " + xhr.responseText);
}
});
});
// It also includes functions to manage the CRFS token
I have been playing with the code. If instead a form I use <input> and <button id='query-button'> it renders the response without reloading the page.
You need to prevent the default submit action of the HTML form, via event.preventDefault().
You can using FormData instead of custom send data, open below links:
How to send FormData objects with Ajax-requests in jQuery?
https://developer.mozilla.org/en-US/docs/Web/API/FormData

Resources