Using bootstrap I am working with the collapse function to collapse my table sort of like this. I am hooking into the collapse js with the following:
<script type="text/javascript">
$('#demo1').on('shown.bs.collapse', function () {
that = $(this);
$.ajax({
url:'{{ (path('orders')) }}',
type: "POST",
dataType: "json",
data: {
"id": "1"
},
async: true,
success: function (data)
{
console.log(data)
$('div#demo1').html('<img src="data:image/png;base64,' + data.output + '" />');
}
});
return false;
});
</script>
How can I either pass a value to that function or get the name of the dom element that passed it (i.e. #demo1)? I basically need to pass a value to pass as the id value to the ajax POST.
I cannot statically map the values as I'm just generating the rows based off a database return. The twig is
{% for x in search%}
<tr data-toggle="collapse" data-target="#demo{{ loop.index }}" class="accordion-toggle">
<th>{{ x.id}}</th>
<tr>
<td colspan="5" class="hiddenRow">
<div class="accordian-body collapse" id="demo{{ loop.index }}">
Demo{{ loop.index }} data
</div>
</td>
</tr>
{% endfor %}
Basically in the above I'm needing access to x.id to pass to the bootstrap jQuery
If you're targeting multiple collapses, you should use class selector instead of the id selector:
$(function(){
$('.accordian-body.collapse').on('show.bs.collapse', function(e) {
...
});
});
You can get the collapsed DOM element id from e.target.id.
// If using your example:
// if you click on 1st row you will get:
demo1
// if you click on 2nd row you will get:
demo2
// if you click on 3rd row you will get:
demo3
If you have more data you need to grab other than the id, you can bind the data using data- when you construct your HTML, and then jQuery on the target object and go from there:
HTML
<div class="accordian-body collapse" id="demo{{ loop.index }}"
data-index="{{ loop.index }}">
Demo{{ loop.index }} data
</div>
JavaScript
$('.accordian-body.collapse').on('show.bs.collapse', function(e) {
let $collapsedTarget = $(e.target),
index = $collapsedTarget.data('index');
});
I am not sure if I have answered your question or not, as your question is not clear to me either.
This is not a clear question, as the answer depends...
It should be easy, in Javascript you set up a variable outside of the function and declare it so it is global. I.e.
<script>let variable;</script>
or
<script>let variable = 0;</script>
or
<script>let variable = 'word';</script>
Then whether hard code change it or change it via a form entry or select item, as it is global it will be accessible within your function as variable.
You could try something like this:
{% for x in search <script>let variable=x;</script> %}
Just in case someone wants to see the end code (based off David Liang's answer) for how to do this...
twig:
{% for x in search%}
<tr data-toggle="collapse" data-target="#demo{{ loop.index }}" class="accordion-toggle">
<th>{{ x.id}}</th>
<tr>
<td colspan="5" class="hiddenRow">
<div class="accordian-body collapse" id="demo{{ loop.index }}" data-index="{{ x.id }}">
Loading...
</div>
</td>
</tr>
{% endfor %}
script:
<script type="text/javascript">
$('.accordian-body.collapse').on('shown.bs.collapse', function (e) {
let $collapsedTarget = $(e.target),
record_id = $collapsedTarget.attr('data-index');
$.ajax({
url:'{{ (path('orders')) }}',
type: "POST",
dataType: "json",
data: {
"id": record_id.toString()
},
async: true,
success: function (data)
{
console.log('Record ID: ' + record_id);
console.log(data)
$(e.target).html('<img src="data:image/png;base64,' + data.output + '" />');
}
});
return false;
});
</script>
and it will replace "Loading..." with whatever you put in the .html() (in my case the img tag).
Related
I want to dynamically filter my querySet using the value of my input field with Ajax.
Right now I’m trying something like this:
Template:
<div class="card mt-3">
<div class="card-body">
<form action="" form="get">
<input data-url="{% url 'klantbeheer' %}" class="zoekklanten" name="q" type="text" placeholder="Zoek op contactnaam...">
</form>
{% if object_list %}
<div class="single-table">
<div class="table-responsive">
<table class="table text-center">
<thead class="text-uppercase bg-dark">
<tr class="text-white">
<th scope="col">Bedrijfsnaam</th>
<th scope="col">Contactnaam</th>
<th scope="col">Locatie</th>
<th scope="col">Actie</th>
</tr>
</thead>
<tbody>
{% for user in object_list %}
<tr>
<td>{{ user.bedrijfsNaam }}</td>
<td>{{ user.contactNaam }}</td>
<td>{{ user.adres }}</td>
<td>
<i class="fas fa-edit"></i>
<i class="fas fa-trash-alt"></i>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% else %}
<p>Geen gebruikers gevonden</p>
<p>
Maak klant aan
</p>
{% endif %}
</div>
</div>
View:
class ManageUserView(SuperUserRequired, ListView):
model = User
template_name = 'webapp/klant/beheerklant.html'
#Query based upon contactName
def get_queryset(self, query):
#Contactnaam bevat QUERY EN superuser is vals.
object_list = self.model.objects.filter(contactNaam__icontains=query).exclude(is_superuser=True)
return object_list
def post(self, request, *args, **kwargs):
query = self.request.POST.get('query', '')
print(query)
self.get_queryset(query)
Jquery:
$('.zoekklanten').on('keyup', function(){
var url = $(this).data('url')
var query = $(this).val();
$.ajax({
url:url,
type:'POST',
data:{
'query':query
},
dataType: 'json',
beforeSend: function(xhr, settings){
if(!csrfSafeMethod(settings.type) && !this.crossDomain){
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
success: function(result){
},
error: function(data){
}
})})
I’m getting "get_queryset() missing 1 required positional argument: ‘query’ " error. I assume calling the get_queryset function inside a post request function isn’t the way to go about this.
What would be the best way to filter dynamically using Ajax in Django?
Your problem is that the method ListView.get_queryset() is normally defined without any extra parameter, so when it's called by Django implicitly, it does not pass any value to the new extra parameter query you have added there.
So either use self.request.POST.get('query', '') in get_queryset() directly instead of passing it there as a parameter or add a default value to the parameter.
However using a user input and passing it directly into SQL query is risky as it might lead to an SQL injection (even though Django tries to sanitize the value).
def get_queryset(self, query=None):
# either set default value for `query` here^
if not query:
return super().get_queryset()
# or take the value from `POST` here instead of passing it as a parameter to the method
query = self.request.POST.get('query')
object_list = self.model.objects.filter(contactNaam__icontains=query).exclude(is_superuser=True)
return object_list
I have a problem with my Laravel view. I am getting the desired data through ajax and I can also show that data in my view. However, I found that whenever I select something in my dropdown then the data appears, but the overall layout gets duplicated. I see my console and find that inside the table I have another layout created after selecting something with the dropdown. I have my code here please take a review of it.
<select>`enter code here`
#foreach(App\StudentsClass::all() as $class)
<option id="class{{$class->id}}" value="{{$class->id}}">{{$class->class_name}}</option>
#endforeach
</select>
<table id="studentsData" class="table table-striped table-bordered table-list-search">
<thead>
<tr>
<th>#</th>
<th>Student ID</th>
<th>Student Name</th>
<th>Attendance</th>
</tr>
</thead>
#foreach($students as $student)
<tbody>
<tr>
<th>{{$student->id}}</th>
<td>{{$student->student_id}}</td>
<td>{{$student->first_name}} {{$student->last_name}}</td>
<td>
<div class="form-group">
<select class="form-control" id="gender">
<option>Present</option>
<option>Absent</option>
<option>Leave</option>
</select>
</div>
</td>
</tr>
</tbody>
#endforeach
</table>
<a class="fas fa-folder-open btn btn-success float-right mb-4 mr-2"> Save</a>
</div>
<script>
$(document).ready(function () {
#foreach(App\StudentsClass::all() as $class)
$("#class{{$class->id}}").click(function () {
var classes = $("#class{{$class->id}}").val();
$.ajax({
url: '{{url('/students/attendance')}}',
type: "GET",
dataType: "html",
data: 'class_id=' + classes,
success:function(response) {
// console.log(response);
$('table[id=studentsData]').html(response);
}
});
});
#endforeach
});
Its hard to say without knowing exactly that is returned by the ajax call -- but it sounds like you may be returning the either a full view (Everything from <html> to </html>) and inserting it into the table ... or the full html markup for a table, creating new nested tables on each ajax call.
Can you share the result of your ajax call? (What you see with console.log(response); )
Also, I don't think this is related but noticed a few things you could do to your code to simplify. For example, Id suggest changing your dropdown's structure a bit and giving it an ID like so ...
<select id="class_select">
#foreach(App\StudentsClass::all() as $class)
<option value="{{$class->id}}">{{$class->class_name}}</option>
#endforeach
</select>
And then rather than looping through each class and adding dedicated function, you could adjust your javascript to find the class ID and trigger the ajax call each time the dropdown is changed.
<script>
$(document).ready(function(){
$('#class_select').change(function(){
var class = $(this).val();
$.ajax({
url: '{{url('/students/attendance')}}',
type: "GET",
dataType: "html",
data: 'class_id=' + classes,
success:function(response) {
// console.log(response);
$('#studentsData').html(response);
}
});
});
});
</script>
Hope that helps! If we could see what the ajax call returns I think we could give a better answer.
I am having problems trying to update a block of my site (which includes another templates) by issuing an Ajax call. The that needs to be updated works just fine, but the JS script that is inside that template does not work (before, I was just adding the full request to my template, but that caused to have twice the content of the parsed template, but JS scripts were working).
PD: I am kind new to JS and have some experience with Django (still just digging in the world of Web Apps development).
My template:
{% load staticfiles %}
<script>
$(document).ready(function() {
var current_item_id = null;
var current_item_title = null;
var selected_items = null;
// Selección en las tablas
$('.table tr').on('click', function() {
$(this).toggleClass('selected');
});
// Comportamiento del toolbar flotante
$('.table tr').on('click', function() {
selected_items = $('.selected');
current_item_id = $(this).attr('id');
current_item_title = $(this).attr('name');
if (selected_items.length === 0) {
$('.modify-big').attr('disabled', true);
$('.delete-big').attr('disabled', true);
}
else if (selected_items.length > 1) {
$('.modify-big').attr('disabled', true);
}
else {
$('.modify-big').attr('disabled', false);
$('.delete-big').attr('disabled', false);
}
});
});
</script>
<div id='notifications'>
{% if notifications %}
<table class="table">
<thead>
<tr>
<!--<th class="text-left table-id">ID del Item</th>-->
<th class="text-left">Item</th>
<th class="text-left">Link de descarga</th>
<th class="text-left">Plantilla</th>
</tr>
</thead>
<tbody class="table-hover">
{% for notification in notifications %}
<tr id='{{ notification.item_id }}' name='{{ notification.item_title }}'>
<!--<td class='text-left'>{{ notification.item_id }}</td>-->
<td class='text-left'>
<a class='tooltip-right' href='#' tooltip='Ver item'>
<img src="{% static 'images/icon_notification_details.png' %}">
</a>
{{ notification.item_title }}
</td>
<td class='text-left'>
{% if notification.download_link %}
<a href='{{ notification.download_link }}' target='_blank'>{{ notification.download_link }}</a>
{% else %}
---
{% endif %}
</td>
<td class='text-left'>{{ notification.email_template.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if first_time %}
<p class='info-msg first-time'>Últimas notificaciones agregadas.</p>
{% else %}
<div class="pagination">
<span class='step-links'>
{% if notifications.has_previous %}
<button class='previous' onclick='search_notifications("", "{{ notifications.previous_page_number }}");'></button>
{% else %}
<button class='previous' disabled></button>
{% endif %}
<span class='current'>
Página {{ notifications.number }} de {{ notifications.paginator.num_pages }}
</span>
{% if notifications.has_next %}
<button class='next' onclick='search_notifications("", "{{ notifications.next_page_number }}");'></button>
{% else %}
<button class='next' disabled></button>
{% endif %}
</span>
</div>
{% endif %}
{% else %}
<p class="info-msg info">No se han encontrado notificaciones.</p>
{% endif %}
</div>
Ajax Call:
search_notifications = function(first_time=false, page=null) {
show_div_loader($('#notifications'));
$.ajax({
url: "{% url 'notifications_loader' %}",
data: {
'search_notifications_query': $('#search-notifications-query').val(),
'search_notifications_listing': $('#search-notifications-listing option:selected').val(),
'first_time': first_time,
'page': page,
},
success: function(data){
// Solo necesitamos actualizar la sección #notifications
data = $(data).filter('#notifications').html();
notifications.html(data);
hide_div_loader($('#notifications-container'));
}
});
};
My view:
def notifications_loader(request):
[...]
return render(request, 'notifications_search_result.html', {'notifications': notifications, 'first_time': first_time})
As you can see in the Ajax sucess function, I do:
data = $(data).filter('#notifications').html();
notifications.html(data);
Before, I was doing:
notifications.html(data);
This last one was adding twice the parsed template but JS script inside it were working.
What I am doing wrong?
Thanks in advance.
EDIT:
I don't know if is the best way, but I've added a 'container' to my code and just insert parsed themplate there:
In my main template:
<div id='notifications-container'>
<!--{% include 'notifications_search_result.html' %}-->
</div>
JS scripts are working again and I don't have twice the parsed template. Now, for I was reading I think this is not the best way to work with Django and Ajax or I am wrong? Maybe I just need to return the view as JSON and replace only the needed data?
Still I have doubs about Ajax+Django and best practices way.
Thanks.
When doing AJAX using Django I do it this way:
Define a route(view) that will serve your default template containing your ajax call script.
Add another route(view) for the ajax call:
def auto_complete(request):
# do some actions and put the results in var
return HttpResponse(simplejson.dumps(var),content_type='application/json')
And you will call the second route in your ajax call
Hope it helps you
I'm trying to develop a simple task list with PHP. I have a list of tasks using twig http://twig.sensiolabs.org/ for each loop. The checkbox is checked if the task is marked as done. My question is how can I attach to each checkbox a script to make ajax calls with different parameters so the server knows which task is being checked?
<table>
<thead>
<tr>
<th>Task</th>
<th>Valmis</th>
</tr>
</thead>
<tbody>
{% for task in tasks %}
<tr>
<td>{{task.description}}</td>
<td><input type="checkbox" {{ task.done ? "checked" : "" }} ></td>
</tr>
{% endfor %}
</tbody>
</table>
I add a class for enable ajax call to a form, and make it via a POST to the server and manage the response, like this example:
Javascript code:
$(document).ready(function() {
$('.lista-proroghe-item').each(function(){
$(this).find('.perform-ajax-request-button').click(function(){
var form = $(this).closest("form"), action = form.attr('action');
var currentButton = $(this);
var currentMessage = $(this).next('.proroga-messaggio');
$(this).attr('disabled', 'disabled');
$(this).html('Processing...');
$.ajax({
url: action,
type: "POST",
data: form.serialize(),
success: function(data) {
// console.log(data);
$(currentButton).hide();
$(currentMessage).html('<span>'+data.description+'<br>'+data.extendedMessage+'</span>');
}
});
e.preventDefault();
return false;
})
})
});
Twig code:
{% for extension in assignation.contract.contractModificationDurations %}
<li class="lista-proroghe-item">
<form action="{{ path('contractExtension', {'idContractModification' : extension.idContractModification, 'userid':user.id }) }}">
Element
<button class="button small perform-ajax-request-button right"><span class="refresh">to task</span></button>
<div class="proroga-messaggio"></div>
</form>
</li>
{% else %}
<li>
Nessuna proroga trovata
</li>
{% endfor %}
Hope this help.
I'm attempting to access the contents of a cell, within my django template using javascript.
The table can contain x rows. When any of the "click to show" links (in the TEST column) are clicked, I would like the row's {{ i.description }} to be passed through to my views (ajax_test function), the "click to show" link to disappear and be replaced with the returned html from the view. I've included my terrible javascript attempt, knowing full well that this doesn't do what I'm asking. If anyone could help, it would be very much welcomed.
Template:
{% extends "myapp/base.html" %}
{% block content %}
<p>You searched for: <strong>{{ query }}</strong></p>
{% if elements %}
<p>Found {{ elements|length }} Element{{ elements|pluralize }}.</p>
<div class="datagrid"><table>
<thead><tr>
<th>Name</th>
<th>Description</th>
<th>Type</th>
<th>Parameter Arguments</th>
<th>TEST</th>
<tbody>
{% for i in elements %}
<tr class="{% if forloop.counter|divisibleby:2 %}alt{% else %}{% endif %}">
<td>{{ i.name }}</td>
<td><div id="desc">{{ i.description }}</div></td>
<td>{{ i.type }}</td>
<td>{% for a in i.parameter.all %}{{ a.argument }}{% endfor %}</td>
<td><div class="clicks">click to show</div></td>
</tr>
{% endfor %}
</tbody>
</table></div>
{% endblock %}
Javascript (this is where I haven't got a clue really, the code below is a failed attempt). The code is included as a static file (ajax_test.js, which is loaded from base.html)
$(function(){
var myCell = document.getElementById("desc");
var cellContents = (myCell.innerHTML);
$('.clicks').click(function() {
$.ajax({
type: "POST",
url: "/myapp/test_ajax/",
data: {
'ajax_data' : cellContents,
'csrfmiddlewaretoken' : $("input[name=csrfmiddlewaretoken]").val()
},
success: ajaxSuccess,
dataType: 'html'
});
});
});
function ajaxSuccess(data, textStatus, jqXHR)
{
$('.here').html(data); //I would like to put this in the "click to show" cell. I was placing it in a random div for testing.
}
test_ajax view:
def ajax_test(request):
if request.POST:
ajax_data = request.POST['ajax_data']
ajax_query = #some generic lookup using ajax_data
return render_to_response('myapp/ajax_test.html', {'ajax_query': ajax_query})
ajax_test template (to be returned to the cell):
{{ ajax_query }}
Try this:
html
<td><div class="clicks"><a class="click-to-show" href="#" data-desc="{{ i.description }}">click to show</a></div></td>
javascript
$(function(){
$('.click-to-show').click(function(e) {
$.ajax({
type: "POST",
url: "/myapp/test_ajax/",
data: {
'ajax_data' : $(e.target).attr("data-desc"),
'csrfmiddlewaretoken' : $("input[name=csrfmiddlewaretoken]").val()
},
success: function ajaxSuccess(data, textStatus, jqXHR) {
$(e.target).parent().html(data);
},
dataType: 'html'
});
});
});
As you can see we keep the DOM relative to link element all the time, since we render rows multiple times, this will make sure we update the correct row.