every one ,I am using django's template language with javascript to do "clicked image button change image" ,however,the result I got was only can change the last button.I do not know why what's wrong about the code , here is my
indext.html
{% extends 'base.html' %}
{% load static %}
{% block title %}
Homepage - {{ block.super }}
{% endblock title %}
{% block content %}
<script>
function setColor(e, btn, color) {
var target = e.target,
count = +target.dataset.count;
target.style.backgroundColor = count === 1 ? "#7FFF00" : '#FFFFFF';
target.dataset.count = count === 1 ? 0 : 1;
}
var img_array = [ src="{% static "img/published.png" %}" , src="{% static "img/draft.png" %}"];
i = 0;
{% for post in posts %}
function myFunction({{ post.model_number }}) {
i++;
document.getElementById("{{ post.model_number }}").src = img_array[i];
if (i == img_array.length - 1) {
i = -1;
}
}
{% endfor %}
</script>
<table class="table table-bordered">
<tr>
<td>產品編號</td><td>產品名稱</td><td>建立日期</td><td>產品圖片</td><td>最後修改日期</td><td>產品說明</td><td>建立者</td><td>修改者</td><td></td>
</tr>
{% for post in posts %}
<tr>
<td> {{ post.model_number }} </td>
<td>{{ post.name }}</td>
<td>{{ post.created }} </td>
<td> <img src="{% if post.image %} {{ post.image.url }}{% else %}{% static "img/no_image.png" %}{% endif %}" height="100" width="100"> </td>
<td>{{ post.modified }} </td>
<td>{{ post.feature }}</td>
<td>{{ post.user }}</td>
<td>{{ post.useredit }}</td>
{% for cp in post.cataloggroup.all %}
<td> {{cp }}</td>
{% endfor %}
<td><a href="{% url 'edit_thing' slug=post.slug %}"><input class="button0 button2" type="button" id="button" value="編輯" style="color:#fffff0" onclick="setColor(event, 'button', '#101010')"; data-count="1" /><a></td>
<td><button onclick="myFunction({{ post.model_number }})"><img id="{{ post.model_number }}" src="{% static "img/published.png" %}" width="50" height="30"></button></td>
</tr>
{% endfor %}
</table>
{% include "pagination.html" with page=posts %}
{% endblock content %}
and it will render the web
however, when I click the top button ,it will change the bottom button,I have to let every button clicked can change image
above image I clicked top button but changed the bottom button's image "published ---> draft"
I have to let every button clicked can changed it's own image,how can I do it?
It is due to the fact you have your myFunction() definintion inside a <script> tag that is entered into the HTML every iteration of your for loop in django.
This means the function is constantly being redefined and therefore myfunction functionality will always be that of the last iteration.
If you define myFunction() outside of your django loop and pass in the model number to the function (as below) then it should work as expected`
function myFunction(model_number) {
i++;
document.getElementById(model_number).src = img_array[i];
if (i == img_array.length - 1) {
i = -1;
}
}
ok,I solve the problem
index.html
<script>
...........
var img_array = [ src="{% static "img/published.png" %}" , src="{% static "img/draft.png" %}"];
i = 0;
{% for post in posts %}
function a{{ post.model_number }}() {
i++;
document.getElementById("{{ post.model_number }}").src = img_array[i];
if (i == img_array.length - 1) {
i = -1;
}
}
{% endfor %}
</script>
<table class="table table-bordered">
<tr>
{% for post in posts %}
<tr>
.........
<td><button onclick="a{{ post.model_number }}()"><img id="{{ post.model_number }}" src="{% static "img/published.png" %}" width="50" height="30"></button></td>
</tr>
{% endfor %}
</table>
Related
I have created a page where users can enter details to forms relating to a parent model (Patient) and two child models (CurrentMed and PastMed) linked to that parent.
Both the child forms use dynamic formsets where the user can add or delete rows to the form. My problem is only the last row of the currentmed and pastmed formsets is saving to my database when the user submits the form?
models.py
class Patient(TimeStampedModel):
# get a unique id for each patient - could perhaps use this as slug if needed
patient_id = models.UUIDField(primary_key=True, unique=True, default=uuid.uuid4, editable=False)
name = models.CharField("Patient Name", max_length=255)
creator = models.ForeignKey(
settings.AUTH_USER_MODEL,
null=True,
on_delete=models.SET_NULL)
class Med(TimeStampedModel):
med_name = models.CharField(“med name“, max_length=20)
dose = models.IntegerField("Dose (mg)", default=0)
timepoint = models.CharField(
"timepoint", max_length=20,
choices=[('current','current'), ('past', 'past')], default='unspecified')
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
class Meta:
abstract = True
class CurrentMed(Med):
timepoint = models.CharField(
"", max_length=20,
choices=[('current','current'), ('past', 'past')], default='current')
class PastMed(Med):
timepoint = models.CharField(
"", max_length=20,
choices=[('current','current'), ('past', 'past')], default='past')
forms.py
from .models import CurrentMed, PastMed, Patient
CurrentmedFormSet = inlineformset_factory(
Patient, CurrentMed, fields=("med_name", "dose",), extra=2)
PastmedFormSet = inlineformset_factory(
Patient, PastMed, fields=("med_name", "dose",), extra=2)
class PatientForm(ModelForm):
class Meta:
model = Patient
fields = ['name', 'sex', 'age', 'diagnosis']
views.py
class PatientAddView(LoginRequiredMixin,TemplateView):
model = Patient
template_name = "../templates/patient/add.html"
def get(self, *args, **kwargs):
patient_form = PatientForm
currentmed_formset = CurrentmedFormSet(queryset=CurrentMed.objects.none())
pastmed_formset = PastmedFormSet(queryset=PastMed.objects.none())
return self.render_to_response({'currentmed_formset': currentmed_formset,
'pastmed_formset': pastmed_formset,
'patient_form': patient_form})
def post(self, *args, **kwargs):
form = PatientForm(data=self.request.POST)
currentmed_formset = CurrentmedFormSet(data=self.request.POST)
pastmed_formset = PastmedFormSet(data=self.request.POST)
if form.is_valid():
patient_instance = form.save()
if currentmed_formset.is_valid():
med_name = currentmed_formset.save(commit=False)
for med in med_name:
med.patient = patient_instance
med.save()
if pastmed_formset.is_valid():
med_name = pastmed_formset.save(commit=False)
for med in med_name:
med.patient = patient_instance
med.save()
return redirect(reverse(
'patient:treatment_detail',
kwargs={"patient_id": patient_instance.patient_id}))
html
{% extends "base.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block javascript %}
<script type="text/javascript" src="{% static 'js/jquery/dist/jquery-1.3.2.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery.formset.js' %}"></script>
<script type="text/javascript">
$(function() {
$('#currentmeds_table tbody tr').formset({
prefix: 'current_meds'
})
});
$(function() {
$('#pastmeds_table tbody tr').formset({
prefix: 'past_meds'
})
});
</script>
<style type="text/css">
.delete-row {
margin-left:5px;
}
</style>
{% endblock %}
{% block content %}
<div>
<div class="entry">
<form id="form" method="POST">
<h1>Patient Details</h1>
{% csrf_token %}
<h3>Demographics</h3>
{{patient_form}}
<h3>Current Medication</h3>
<table id="currentmeds_table" border="0" cellpadding="0" cellspacing="5">
<thead>
<tr>
<th scope="col">Medication</th>
<th scope="col">Dose</th>
</tr>
</thead>
<tbody>
{% for form in currentmed_formset %}
<tr id="{{ form.prefix }}-row"></tr>
<td>
{% for fld in form.hidden_fields %}{{ fld }}{% endfor %}
{% if form.instance.pk %}{{ form.DELETE }}{% endif %}
{{ form.med_name}}
</td>
<td>{{ form.dose }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{currentmed_formset.management_form}}
<h3>Past Medication</h3>
<table id="pastmeds_table" border="0" cellpadding="0" cellspacing="5">
<thead>
<tr>
<th scope="col">Medication</th>
<th scope="col">Dose</th>
</tr>
</thead>
<tbody>
{% for form in pastmed_formset %}
<tr id="{{ form.prefix }}-row"></tr>
<td>
{% for fld in form.hidden_fields %}{{ fld }}{% endfor %}
{% if form.instance.pk %}{{ form.DELETE }}{% endif %}
{{ form.med_name}}
</td>
<td>{{ form.dose }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{pastmed_formset.management_form}}
<button type="submit">Create Patient</button>
</form>
</div>
</div>
{% endblock %}
The prefixes in the javascript were incorrect, found the correct ones by looking at the html source, instead of
$('#currentmeds_table tbody tr').formset({
prefix: 'current_meds'
})
Should have been
$('#currentmeds_table tbody tr').formset({
prefix: 'currentmed_set'
})
cart.js
this is not working
nothing is printed in the console or some declaration is wrong
answer quickly
var updateBtns = document.getElementsByClassName('update-cart')
for(var i=0 ; i<updateBtns.length ; i++)
{
updateBtns[i].addEventListener('click',function(){
var productId = this.dataset.product
var action = this.dataset.action
console.log(productId,action)
})
}
is there any mistake in html code
{% for product in products %}
{% if product.category == "Dosa" %}
<div class="product">
<tr>
<td><h5>{{ product.name }}</h5></td>
<td><h5>{{ product.price }}</h5></td>
<td><button data-product={{product.id}} data-action="add" class="btn btn-warning btn-add update-cart">Add to cart</button></td>
</tr>
</div>
{% endif %}
{% endfor %}
Seems to be working perfectly. I would suggest to please check once in incognito/Private mode. Might be a problem of cache...
I'm trying to get the child nodes from a table, multiply that and show that on a input field. I have tried using textContext but it only returns first value not the later ones.
My Javascript code is:
function add() {
console.log("this is working")
var x = parseInt(document.getElementById("id_quantity").value);
console.log(x, "value of x");
var y = document.getElementById("quantity").textContent;
document.getElementById("id_quantity_p1").value = x * y;
This is my HTML markup:
<div class="col-md-6 col-sm-8 col-12">
<form method="post" id="MaterialRequestForm" data-kit-url="{% url 'employee:ajax_load_kit' %}" onkeyup="add()"
data-product-url="{% url 'employee:ajax_load_product' %}"
novalidate>
{% csrf_token %}
{{ form|crispy }}
<button type="submit">Save</button>
<div id="products-table" class="col-md-12 col-sm-8 col-12 product-table-ajax">
</div>
</form>
</div>
And This is my table's HTML code:
{% for product in products %}
<tr>
<td>{{ product.id }}</td>
<td>{{ product.product_name }}</td>
{% for i in quantities %}
{% if forloop.counter == forloop.parentloop.counter %}
<td id="quantity">{{ i }}</td>
{% endif %}
{% endfor %}
{% endfor %}
In this <td id-"quantity" returns multiple values and I want first two of it.
They are in django HTML template
In this I want to enter quantity and I want that it should get multiplied by content Std Qty in column and get filled in "quantity p1", "quantity p2", "quantity p3". eg. quantitystdQty1=quantityP1, quantitystdQty[2]=quantityP2, quantity*stdQty[3]=quantityP3 etc. For that I need specific elements in my <td>. Please help!
I did that with a different way:
I attached different ID's with the form and then instead of fetching child of I assigned different ID's to all the and then used getElementByID:
{% for product in products %}
<tr>
<td>{{ product.id }}</td>
<td>{{ product.product_name }}</td>
{% for i in quantities %}
{% if forloop.counter == forloop.parentloop.counter %}
<td id="q{{ forloop.counter }}">{{ i }}</td>
{% endif %}
{% endfor %}
{% endfor %}
</tr>
And then changed my js accordingly:
function add() {
console.log("this is working")
var x = parseInt(document.getElementById("id_quantity").value);
console.log(x, "value of x");
var y =document.getElementById("q1").textContent;
var y1 =document.getElementById("q2").textContent;
var y2 =document.getElementById("q3").textContent;
var y3 =document.getElementById("q4").textContent;
var y4 =document.getElementById("q5").textContent;
document.getElementById("id_quantity_p1").value = x * y;
document.getElementById("id_quantity_p2").value = x * y1;
document.getElementById("id_quantity_p3").value = x * y2;
document.getElementById("id_quantity_p4").value = x * y3;
document.getElementById("id_quantity_p5").value = x * y4;
It will obviously only give you back the first one due to the fact that you are using a body.getElementById function, which only returns the very first element with the said id you look for.
For getting all the values you need, I suggest you could instead remake "id_quantity" into a class instead.
With that being done, use body.getElementsByClassName instead, write a loop that stores the data from every node of "id_quantity" and loop it back into the fields where you multiply them.
Here's a very quick example of what I mean
HTML:
<div id="container">
<div id="color-div">
<table>
<thead>
<th>1</th>
<th>2</th>
</thead>
<tbody>
<tr>
<td class="input">5</td>
<td class="output"></td>
</tr>
<tr>
<td class="input">7</td>
<td class="output"></td>
</tr>
<tr>
<td class="input">10</td>
<td class="output"></td>
</tr>
</tbody>
</table>
</div>
</div>
Javasript:
let arr = [];
const $input = document.getElementsByClassName("input");
const $output = document.getElementsByClassName("output");
for (let i = 0; i < $input.length; i += 1) {
arr.push($input[i].innerHTML);
}
for (let i = 0; i < $output.length; i += 1) {
$output[i].innerHTML = arr[i] * 5;
}
I am trying to get the id which is dynamically generated. I am using a class name to access it. If I click on the td item once, there is no alert. But when I click twice I will get the alert (for the first time). If I click on the second item, I get an alert two times. If on third, I get it three times and so on. What is the error?
My JavaScript code:
function myFunction() {
$('.task0').click(function() {
var x = $(this).data('id');
alert(x);
});
}
My HTML-Flask code:
<tbody>
{% set ns = namespace(num=1) %}
{% for task in tasklist %}
<tr>
<td>{{ ns.num }}</td>
<td class="task0" data-id="{{ task[0] }}"><a href="javascript:myFunction();" >{{ task[0] }}</a></td>
{% for i in range(1,task|count) %}
<td>{{ task[i] }}</td>
{% endfor %}
</tr>
{% set ns.num = ns.num+1 %}
{% endfor %}
</tbody>
You are calling the function twice. The .click you are using in jquery is already calls the function then your make the a tag call the JavaScript function as well. Remove the call to the function from the a tag
Every time you click on td you attach one more listener. you need to attach listner at once for all dynamically created elements.
remove javascript function call in your html part.
and change your javascript as below.
$(document).on(click, '.tasklink', function(e){
e.preventDefault();
var x = $(this).parents('td.task0').data('id');
alert(x);
})
<tbody>
{% set ns = namespace(num=1) %}
{% for task in tasklist %}
<tr>
<td>{{ ns.num }}</td>
<td class="task0" data-id="{{ task[0] }}"><a class="tasklink" href="#" >{{ task[0] }}</a></td>
{% for i in range(1,task|count) %}
<td>{{ task[i] }}</td>
{% endfor %}
</tr>
{% set ns.num = ns.num+1 %}
{% endfor %}
</tbody>
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