JS: pass variable onclick - javascript

I'm trying to pass a variable to a function, I know there are many topics about this, and I've nearly tried all suggestions, but still can't get it to work, these are my attempts:
edit: without the onclick, everything is working fine
var filename = file.name;
<button class="btn btn-danger delete" onclick="deleteImage(\''+filename+'\');">
results in: Uncaught SyntaxError: Unexpected token ILLEGAL
<button class="btn btn-danger delete" onclick="deleteImage("'+type+'");">
results in (alert): 'filename'
<button class="btn btn-danger delete" onclick="deleteImage('" + filename + "');">
results in: Uncaught SyntaxError: Unexpected token ILLEGAL
<button class="btn btn-danger delete" onclick="deleteImage(" + filename + ");">
result in: Uncaught SyntaxError: Unexpected token }
this is the full code (modified, blueimp fileuploader)
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
{% if (file.error) { %}
<td></td>
<td class="name"><span>{%=file.name%}</span></td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
<td class="error" colspan="2"><span class="label label-important">Error</span> {%=file.error%}</td>
{% } else {
// add the image urls to the file inputbox
var filename = file.name;
var prev = $("#mFile").val();
$("#mFile").val(prev + file.name + ",");
%}
<td class="preview">{% if (file.thumbnail_url) { %}
<img src="modules/mod_stern_form_prijsopgave/upload/server/php/files/thumbnail/{%=file.name%}">
{% } %}</td>
<td class="name">
{%=file.name%}
</td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
<td colspan="2"></td>
{% } %}
<td>
<button class="btn btn-danger delete" onclick="deleteImage('" + filename + "');" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}"{% if (file.delete_with_credentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
<i class="icon-trash icon-white"></i>
<span>Verwijderen</span>
</button>
</td>
</tr>
{% } %}
</script>
and testing like this:
function deleteImage(filename) {
alert(filename);
}
what am I doing wrong? Thanks for your advice

try the template format for onclick value:
onclick="deleteImage('{%=filename%}');"
try file.name as well
onclick="deleteImage('{%=file.name%}');"

<button id="deleteOnClick" class="btn btn-danger delete">...</button>
and in javascript:
document.getElementById("deleteOnClick").onclick = function(){deleteImage(filename);}
edit:
if you want to delete the file specified only by the original filename value:
var deleteByFile = (function (filename){
return function(){deleteImage(filename);};
}(filename));
document.getElementById("deleteOnClick").onclick = deleteByFile

You can't access JS variables from your HTML. You must do something like this:
var filename = 'testing';
document.getElementById('testdiv')
.setAttribute('onclick', "alert('" + filename + "')");
filename = 'more testing';
Here is a fiddle.

try to use onclick="deleteImage(" + filename + ");"

You can set a varaiable like var counter = 1;
Wherever it is required, you can update it like
onclick="updateCount('+counter+')"

Related

update existing post called using dictionary , using ajax - django

i'm trying to go update page . my models.py
class MainGroup(models.Model):
admin = models.ForeignKey(User,on_delete=models.CASCADE)
main_type = models.CharField(max_length=40,unique=True)
date = models.DateTimeField(auto_now_add=True)
my views.py
#login_required
def list_maingroup(request):
lists = MainGroup.objects.all().order_by('-pk')
data = []
for i in lists:
item = {
'id':i.id,
'admin':i.admin.username,
'main_type':i.main_type,
'date':i.date
}
data.append(item)
return JsonResponse({'data':data})
and this is my template
$.ajax({
type:'GET',
url:'/list-main-group',
success:function(data){
data = data.data
spinnerBox.classList.add('non-visible')
var k = '<tbody>'
for(i = 0;i < data.length; i++){
const date = new Date(data[i]["date"]).toLocaleString();
const id = parseInt(data[i]['id'])
// const url = '{% url "products:update_maingroup" %}'
// const my_url = url + "/"+id
k+= '<tr>';
k+= '<td>' + data[i]['id'] + '</td>';
k+= '<td>' + data[i]["admin"] + '</td>';
k+= '<td>' + data[i]["main_type"] + '</td>';
k+= '<td>' + date + '</td>';
k+= '<td align="center">'+
'<button class="btn btn-info bg-info" id="update" data-url='+{% url "products:update_maingroup" id %}+ '><i class="far fa-edit"></i></button>'+
' <button class="btn btn-danger btn-del bg-danger" data-did='+parseInt(data[i]["id"])+"><i class='far fa-trash'></i></button>"+
'</td>';
k+= '</tr>'
}
k+='</tbody>'
tableBody.innerHTML = k
$('#maingroupid').dataTable({
"order": [[ 0, "desc" ]]
});
},
// error:function(error){
// console.log(error)
// }
});
<div class="card-body table-responsive" >
<div id="spinner-box" class="spinner-border text-primary text-center" role="status">
</div>
<table id="maingroupid" class="table table-bordered table-striped text-center">
<thead>
<tr>
<th>#</th>
<th>{% trans "admin" %}</th>
<th>{% trans "name" %}</th>
<th>{% trans "date" %}</th>
<th>{% trans "options" %}</th>
</tr>
</thead>
<tbody id="tableData">
</tbody>
</tfoot>
</table>
</div>
i've tried several ways to achieve that but still none of them worked , and this my views.py to update
#login_required
def update_maingroup(request,id):
obj = get_object_or_404(MainGroup,id=id)
form = MainGroupForm(instance=obj)
if request.is_ajax() and request.method == 'POST' and request.user.is_superuser:
if form.is_valid():
form = MainGroupForm(request.POST,instance=object)
form.save()
return JsonResponse({'success':'success'})
else:
return JsonResponse({'success':False,'error_msg':form.errors,'error_code':'invalid'})
context = {'form':form,'obj':obj}
return render(request,'update_maingroup.html',context)
and my update_maingroup.html
<form id="main-form" role="form" method="POST" action="{% url 'products:update_maingroup' id=obj.id %}">{% csrf_token %}
<div class="card-body">
<div class="form-group row">
<label for="mainGroup" class="col-sm-2 control-label">{% trans "name " %}</label>
<div class="col-sm-10">
{{form.main_type | attr:'id:mainGroup'}}
<p id="main_error" class="alert alert-danger" aria-disabled="true" hidden></p>
</div>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" class="btn btn-success">{% trans "save" %}</button>
</div>
</form>
my urls.py to update
path('maingroup/update/<int:id>',update_maingroup,name='update_maingroup'),
path('list-main-group',list_maingroup,name='list-maingroup'),
but it raise this error :
Reverse for 'update_maingroup' with no arguments not found. 1 pattern(s) tried: ['maingroup/update/(?P[0-9]+)$']
is there something i have to change or add please ? thank you for helping ..
You are mixing Django template tags with JavaScript in your template:
{% url "products:update_maingroup" id %}
This does not work because the template tag only gets evaluate once when the template is rendered, not when the JavaScript get executed.
You have to generate the URL in your view:
#login_required
def list_maingroup(request):
lists = MainGroup.objects.all().order_by('-pk')
data = []
for i in lists:
item = {
'id':i.id,
'admin':i.admin.username,
'main_type':i.main_type,
'date':i.date,
'url': reverse("products:update_maingroup", kwargs={"id": i.id})
}
data.append(item)
return JsonResponse({'data':data})
In your template:
...
'<button class="btn btn-info bg-info" id="update" data-url='+data[i]["url"] + '><i class="far fa-edit"></i></button>'+
...
There are a bunch of alternatives:
you can create a "template URL" with a dummy values and replace those
var urlTemplate = "{% url "products:update_maingroup" 9999 %};
var url = urlTemplate.replace("9999", id);
you can use a third-party library that provides URL reversal in JavaScript, e.g. django-js-reverse

How to prevent table row height glitch during DOM append?

I load my table first, then I dynamically append tags asynchronously.
As soon as those tags are appended, the table row height seems to shift up. How can I prevent that ?
I've tried
.portfolio-table tr {
height: 80px;
}
Table
<table class="table portfolio-table">
<thead class="thin-border-bottom">
<th width="2%">#</th>
<th width="28%">Name</th>
<th width="60%" class="text-left">Tags</th>
<th width="5%">Edit</th>
<th width="5%">Delete</th>
</thead>
<tbody>
<tr>
#foreach ($portfolios as $portfolio)
<td title="{{ $portfolio->id }}">{{ $portfolio->id }} </td>
<td>
<a href="/portfolio/{{ $portfolio->id ?? '' }}/">
{{ $portfolio->name }}
</a>
</td>
<td class="text-right" >
<img src="/assets/fe/img/svg/default.svg" alt="Loading" width="30px">
<p class="portfolioSkillTags text-left" id="{{ $portfolio->id ?? '' }}"></p>
</td>
<td>
<a href="/portfolio/{{ $portfolio->id ?? '' }}/edit" type="button" class="btn btn-info btn-sm">
Edit
</a>
</td>
<td>
<a data-toggle="modal" data-target="#delete_portfolio_{{ $portfolio->id ?? '' }}" type="button" class="btn btn-danger btn-sm">
Delete
</a>
</td>
</tr>
#endforeach
</tbody>
</table>
ajax
$("tbody").each(function(){
$($(this)).find('tr').each(function(){
var selector = $(this);
var id = $(this).find('td:nth-child(1) ').attr('title');
// console.log('%c id = ' + id, "color: green;");
// return false;
var data = {};
data.id = id;
$.ajax({
method: 'POST',
url: '/api/portfolio/' + id + '/skills',
crossDomain: true,
contentType: false,
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('value'),
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded",
"Cache-Control": "no-cache"
},
data: data,
success: function(response){
console.log(id, response);
$('p.portfolioSkillTags#'+ id).prev('img').fadeOut();
for (i = 0; i < response.length; i++) {
// console.log(response[i],id);
var name = response[i]['name'];
var color = response[i]['color'];
$('p.portfolioSkillTags#'+id).prepend('<span class="badge" style="background-color:' + hexToRgb(color,.2) + ';border:' + hexToRgb(color,.7) + ' 2px solid;">' + name + '</span>').fadeIn('slow');
}
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(JSON.stringify(jqXHR));
console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
}
});
});
});
It seems the loading spinner image causes the glitch since it makes the text oveerflow. You can try fix it with some css style like float right so it wont make the paragraph wrap.
<img src="/assets/fe/img/svg/default.svg" style="float: right;" alt="Loading" width="30px">
The issue is with the height of the spinner (svg element). When you loads the data asynchronously, it brings the spinner with larger height. As soon as your API call resolves successfully, the spinner element (which has larger height goes away). Then your other data that can be retained in less height shrinks and produces this issue.
You can fix it with many ways, the simplest one is, keep the height(including paddings) of spinner (svg) element smaller than height of td element. For example:
<img src="/assets/fe/img/svg/default.svg" alt="Loading" width="30px" height="30px">
.portfolio-table tr td {
height: 50px;
}
UODATE
Please rectify the HTML as well, you might want to start the foreach loop outside the start tag of tr HTML element.
#foreach ($portfolios as $portfolio)
<tr>
<td title="{{ $portfolio->id }}">{{ $portfolio->id }} </td>
<td>
<a href="/portfolio/{{ $portfolio->id ?? '' }}/">
{{ $portfolio->name }}
</a>
</td>
<td class="text-right" >
<img src="/assets/fe/img/svg/default.svg" alt="Loading" width="30px">
<p class="portfolioSkillTags text-left" id="{{ $portfolio->id ?? '' }}"></p>
</td>
<td>
<a href="/portfolio/{{ $portfolio->id ?? '' }}/edit" type="button" class="btn btn-info btn-sm">
Edit
</a>
</td>
<td>
<a data-toggle="modal" data-target="#delete_portfolio_{{ $portfolio->id ?? '' }}" type="button" class="btn btn-danger btn-sm">
Delete
</a>
</td>
</tr>
#endforeach
$('p.portfolioSkillTags#'+ id).prev('img').fadeOut();
make this to
$('p.portfolioSkillTags#'+ id).prev('img').hide();
and Please rectify the HTML as well, you might want to start the foreach loop outside the start tag of tr HTML element as mentioned by Prince
I think the problem is a css animation. Try something to globally enforce to disable them to see if the behavior disappear.
* {
animation: none !important;
}
If that is the case disable the animation with the right css selector when you are loading your data.

Function name is not defined at HTMLButtonElement.onclick

Searched a lot of question with the same error but nothing helped.
Am using Python/Django and here the HTML code am trying to make it work.
here is my code:
<tr class="gradeA odd" role="row">
<td class="sorting_1">
{{ item.book_name }}
</td>
<td>{{ item.book_subject }}
</td>
<td>{{ item.book_level }}
</td>
<td>{{ item.book_teacher }}
</td>
<td><input type="number" id="price_{{ item.id }}" style="width: 50px;"/>
</td>
<td><input type="number" id="commission_{{ item.id }}"style="width: 50px;"/>
</td>
<td>
<button class="btn btn-primary" id="submit_button" onclick="addingTheBook_{{ item.id }}()">
إضافة
</button>
</td>
</tr>
<script>
function addingTheBook_{{ item.id }}() {
var the_price = document.getElementById('price_{{ item.id }}');
var the_commission = document.getElementById('commission_{{item.id}}');
window.location.href = '/vip/add/pricelist/' + {{ item.id }} +'/' + the_price.value + '/' + {{ current_vip }} +'/' + the_commission.value + '/';
}
</script>
Whenever I click the button with onclick attribute, it gives me the error addingTheBook_3 is not defined at HTMLButtonElement.onclick
Define the function as:
function addingTheBook_(itemId){
}
And use the itemId variable to fetch price, commission, etc. like below:
var the_price = document.getElementById('price_'+ itemId);
var the_commission = document.getElementById('commission_'+itemId);

Django & js : My formset forms are dependent on each other

I have the following js that adds forms to my template whenever I click on the button ""
function updateElementIndex(el, prefix, ndx) {
var id_regex = new RegExp('(' + prefix + '-\\d+)');
var replacement = prefix + '-' + ndx;
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function addForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
var row = $('.dynamic-form:first').clone(true).get(0);
$(row).removeAttr('id').insertAfter($('.dynamic-form:last')).children('.hidden').removeClass('hidden');
$(row).children().not(':last').children().each(function() {
updateElementIndex(this, prefix, formCount);
$(this).val('');
});
$('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1);
return false;
}
I call this script in my header :
$(function () {
$('#add-row').click(function() {
return addForm(this, 'form');
//$('.add-row').hide();
});
})
and this is my template :
<form action="/caisse" method="POST" enctype="multipart/form-data" id="personForm" data-tiers-url="{% url 'ajax_load_tiers' %}" >{% csrf_token %}{{ form.non_field_errors }}
<table align="center"> <!-- <div class="row" style="padding-left: 24%; padding-top: 3%"></div> -->
<tr>
<td width="10%"></td>
<td><input id="uploadFile" placeholder="Choose File" class="form-control" /></td>
<td><div class="btn btn-primary" id="divInput"><span>importer</span>
{% render_field form1.myfile id="uploadBtn" style=" position: absolute;top: 0;right: 0;margin: 0; padding: 0;font-size: 20px;cursor: pointer;opacity: 0;filter: alpha(opacity=0);" %}
</div></td>
</tr>
</table>
<table style ="border-collapse: separate;border-spacing: 15px;" id="id_forms_table">
{% for form in formset %}
<tr style="border:1px solid black;" id="{{ form.prefix }}-row" class="dynamic-form" >
<td><div class="col-xs-1"><b><p name="np1">1</p></b></div></td>
<td >
{% render_field form.dateOperation class="form-control" %}{{form.dateOperation1.errors}}
</td>
<td>{% render_field form.designation class="form-control" %}{{form.errors}}
</td>
<td>
{% render_field form.typeTiers class="form-control" %}{{form.typeTiers.errors}}
</td>
<td>
{% render_field form.tiers class="form-control" %}{{form.tiers.errors}}
</td>
<td>{% render_field form.numfacture class="form-control" %}{{form.numfacture.errors}}
</td>
<td>{% render_field form.montant class="form-control" %}{{form.montantdebit.errors}}
</td>
<td>{% render_field form.typeMontant %}{{form.typeMontant.errors}}
</td>
</tr>
{% endfor %}
</table>{{ formset.management_form }}
<tr><td><input type="submit" name="ajoutligne" value="Ajouter une ligne" class="btn btn-primary" id="add-row" style="background-color: #8C1944; border-color: #8C1944; float:right;margin: 5px;" onclick=""></td></tr>
The button Ajouter une ligne is the one called on the js to add a new row of my formset.
My problem here is that my forms are not independent.
for example the the last field typeMontant is a Radio button, when I add a new row as bellow :
Only One radio of the four radio buttons got selected. which means that the two rows are dependent on each other.
So what's the problem that makes my forms dependent when I need them to be totally independent of each other.
any help please.
I'm really stucking here, Thank You so much.
That is because the names and the ids of the form fields are the probably the same, since you are adding the same form over and over again, and all your radio buttons reference to the same name.
Django can already handle multiple forms in a page via formsets.
I found a tutorial that helped me a lot to understand and implement it on my own project:
http://whoisnicoleharris.com/2015/01/06/implementing-django-formsets.html

pass a twig variable as a parameter for a javascript function

I have a datatable that I need to add rows dynamically throught t.row.add(), the table is composed by 4 columns, one of them has buttons inside, those buttons are Show & Edit, and they need the {{ row.id }} so the can be shown or edit, the problem is that I don't know how get the twig variable works. Here is my table code:
<table class="table table-striped table-bordered table-hover" id="sample_2">
<thead>
<tr>
<th class="table-checkbox noprint" style="text-align:center;">
<input type="checkbox" class="group-checkable" data-set="#sample_2 .checkboxes" disabled/>
</th>
<th width="40%" style="text-align:center;">
Valoraciones
</th>
<th width="20%" style="text-align:center;">
Estado
</th>
<th width="20%" style="text-align:center;" class="noprint">
Acciones
</th>
</tr>
</thead>
<tbody>
{% for valoracion in valoracion %}
<tr class="odd gradeX" id="fila{{ valoracion.id }}">
<td class="noprint">
<input type="checkbox" class="checkboxes" disabled/>
</td>
<td style="text-align:center;" id="valoracion">
{{ valoracion.descripcion }}
</td>
{% if valoracion.enabled == 1 %}
<td style="text-align:center;" id="estadoValEnable">Activo</td>
{% else %}
<td style="text-align:center;" id="estadoValEnable">Inactivo</td>
{% endif %}
<td style="text-align:center;" class="noprint">
<a class="btn btn-sm default" data-toggle="modal" onclick="showMantenimientoValoracion({{valoracion.id}})">Ver</a>
<a class="btn btn-sm blue" data-toggle="modal" onclick="editMantenimientoValoracionDetails({{valoracion.id}})">Editar</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
and here is the action to create a new row (the create action is in a modal view):
function sendDataCreateValoracionDetails() {
if ($('#CrearValoracionMantenimiento').val() == "") {
Notificacion("error", "La descripión de la competencia no puede estar vacía");
$('#CrearValoracionMantenimiento').focus();
} else {
$.blockUI({
baseZ: 20000,
message: '<h4><img src="{{ asset('
assets / global / plugins / cubeportfolio / cubeportfolio / img / cbp - loading.gif ') }}" /> Guardando datos, por favor espere...</h4>'
});
var form = document.getElementById("formCreateMantenimientoValoracionDetails");
var formData = new FormData(form);
$.ajax({
url: '{{ path('
createValoracionMantenimiento ') }}',
type: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false,
success: function(returndata) {
if (returndata.success == true) {
$.unblockUI();
$('#crearValoracion').modal('hide');
Notificacion("success", "Valoración RP", "Los datos se han guardado correctamente.");
if ($('#EstadoValoracion').attr('checked')) {
var status = "Activo";
} else {
var status = "Inactivo";
}
$(document).ready(function() {
var t = $('#sample_2').addClass('centro').DataTable();
$("#sample_2").each(function() {
t.row.add([
'<tr>' +
'<td><input type="checkbox" class="checkboxes" disabled/></td>',
'<td>' + ($("#CrearValoracionMantenimiento").val()) + '</td>',
'<td>' + status + '</td>',
'<td ><a class="btn btn-sm default" data-toggle="modal" onclick="showMantenimientoValoracion(' {
{
valoracion.id
}
}
')">Ver</a><a class="btn btn-sm blue" data-toggle="modal" onclick="editMantenimientoValoracionDetails(' {
{
valoracion.id
}
}
')">Editar</a></td></tr>',
]).draw(false);
});
});
} else {
if (returndata.success == false) {
$.unblockUI();
Notificacion("error", "Valoración RP", "Existe una valoración igual.");
}
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
Notificacion("error", "Valoración RP", "Ha existido un problema y no se ha podido crear la valoración.");
$.unblockUI();
}
});
}
}
These are my buttons:
<a class="btn btn-sm default" data-toggle="modal" onclick="showMantenimientoValoracion('{{ valoracion.id }}')">Ver</a>
<a class="btn btn-sm blue" data-toggle="modal" onclick="editMantenimientoValoracionDetails('{{ valoracion.id }} ')">Editar</a>
and these are the twig parameters I need to pas inside the functions:
onclick="showMantenimientoValoracion('{{ valoracion.id }}') ///
onclick="editMantenimientoValoracionDetails('{{ valoracion.id }} ')`
here is the function code:
if ($('#EstadoValoracion').attr('checked')) {
var status = "Activo";
} else {
var status = "Inactivo";
}
$(document).ready(function() {
var t = $('#sample_2').addClass('centro').DataTable();
$("#sample_2").each(function() {
t.row.add([
'<tr>' +
'<td><input type="checkbox" class="checkboxes" disabled/></td>',
'<td>' + ($("#CrearValoracionMantenimiento").val()) + '</td>',
'<td>' + status + '</td>',
'<td ><a class="btn btn-sm default" data-toggle="modal" onclick="showMantenimientoValoracion(' {
{
valoracion.id
}
}
')">Ver</a><a class="btn btn-sm blue" data-toggle="modal" onclick="editMantenimientoValoracionDetails(' {
{
valoracion.id
}
}
')">Editar</a></td></tr>',
]).draw(false);
});
});
Thanks everyone :)
A twig variable can be readed by using .twig extension to the file name ends , When I need to use a variable twig inside javascript function, I create it inside file twig. There is not another way.
Just remove the quotes from the twig variable -
onclick="showMantenimientoValoracion('{{ valoracion.id }}')
should be
onclick="showMantenimientoValoracion({{ valoracion.id }})
And in your javascript function add the parameter -
function sendDataCreateValoracionDetails(valoracion_id) {
console.log(valoracion_id)
// Your code goes here
}
This should do it.

Categories

Resources