I am trying to validate a text field using JavaScript. I have an available field and a quantity field. I want to give a message below the quantity field when the quantity entered is greater than available.
What I have tried is:
<form method="post" action="/saveBid" id="reviewForm">
<input type="hidden" name="_token" value="{{csrf_token()}}" />
<input type="hidden" name="truck_name" value="{{truck_name}}" />
<input type="hidden" name="user_name" value="{{auth_user().first_name}}" />
<input type="hidden" name="seller_id" value="{{seller_id}}" />
<div class="form-group row">
<label class="col-sm-4 col-form-label">Select Milege Gap: </label>
<div class="col-sm-8">
<select class="form-select" name="mileage" id="mileage" onchange="getOption()">
<option>Select </option>
{% for p in product_data %}
<option value="{{p.price}},{{p.number_of_products}},{{p.name}},{{p.id}},{{p.number_of_products_sold}}">{{p.name}}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group row">
<label for="available" class="col-sm-4 col-form-label">Available Quantity: </label>
<div class="col-sm-8">
<input type="text" class="form-control" id="available" readonly name="available_qty" />
</div>
</div>
<div class="form-group row">
<label for="truck" class="col-sm-4 col-form-label">Price: </label>
<div class="col-sm-8">
<input type="text" class="form-control" readonly id="truck" name="truck" />
</div>
</div>
<div class="form-group row">
<label for="qty" class="col-sm-4 col-form-label"> Quantity: </label>
<div class="col-sm-8">
<input type="text" id="qty" name="qty" class="form-control" oninput="checkInput(this);" required />
<p id="qty-msg">
</p>
</div>
</div>
<div class="form-group row">
<label for="t_price" class="col-sm-4 col-form-label"> Total Price: </label>
<div class="col-sm-8">
<input type="text" readonly id="t_price" name="t_price" class="form-control" />
</div>
</div>
<div class="form-group row">
<label for="inputBid" class="col-sm-4 col-form-label">Enter Bid Price</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="inputBid" name="bid" oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*)\./g, '$1');"/>
</div>
</div>
<div class="form-group text-center">
<input type="submit" class="btn btn-primary" id="btn" name="send" value="Send" disabled="disabled">
</div>
</form>
Javascript code:
<script>
function getOption()
{
var select = document.getElementById('mileage');
var option = select.options[select.selectedIndex];
var opArr = option.value.split(",");
var price=document.getElementById("truck");
price.value=opArr[0];
var available=opArr[1]-opArr[4];
document.getElementById("available").value=available;
if(available<=0)
{
alert('Out of Stock');
document.getElementById("qty").disabled=true;
document.getElementById("inputBid").disabled=true;
}
}
function checkInput(item)
{
var t_price=document.getElementById("t_price");
var available=document.getElementById("available");
var price=document.getElementById("truck");
var msg=document.getElementById("qty-msg");
if(item.value>available.value)
{
alert("Quantity" +item.value +"Availabe: "+available.value);
item.value='';
msg.innerHTML="* Value must be less than Availabe quantity "+available.value;
msg.style.color="red";
}
t_price.value=price.value*item.value;
}
</script>
What I run this code, If the available quantity is 15, and the quantity entered is 1, it is working fine. But when the quantity entered is other than 1, like 2, 3, or anything, it gives the message. I wish to give a message only when the quantity is greater than 15 like 16, 17, etc.
but when I try to enter 12, it is ok. when I try to enter 3, 4, etc. It gives the validation message. Same in the case, if the available quantity is 20, then quantity entered 2 will work. but 3 or anything 2 will not work. Why this is happening. Why my javascript is not working properly.
My output
When I try to enter 3, this happens in my output
When I try to enter 2 in the quantity field, it is ok
When I try to enter 12, it is working
When I try to enter 4, it is not working
I want to show this error message only when the quantity entered is greater than the available qauntity.
As said in the comments, try to convert your input value (string) in numbers before comparing. So it'll be something like this :
if(parseInt(item.value)>parseInt(available.value))
{
...
}
I am making a project in Django but Im not using Django built-in forms. Rather, I am using html and bootstrap to render forms. On a page, I want to create a quiz. I am doing this via a multi-step form where I input the number of questions on the first form. Then based upon this field, when I hit next, I want to have the same number of the fields for questions and corresponding answers to appear so that I can set them. For example, if I type 5 questions and hit next, it should have 5 fields for me to enter the questions and each question field should have 4 answer fields. Is there a way to dynamically do this?
Please help :(((( This is very important.
Thank you n here is my code snippet
{% block content %}
<div class="row">
<h2 style="color: darkblue;" class="text-center">Add a Quiz</h2>
</div>
<form action="" id="add_test_form" method="POST">
<!--This form will contain the quiz information-->
{% csrf_token %}
<div class="row">
<div class="form-row">
<div class="form-group col-md-6">
<label>Name of test</label>
<input type="text" class="form-control" name="test_name" required>
</div>
</div>
</div>
<div class="row">
<div class="form-row">
<div class="form-group col-md-6">
<label>Number of questions</label>
<input type="number" id="num_qu" class="form-control" name="test_num_questions" min="1"
oninput="validity.valid||(value='')" required>
</div>
</div>
</div>
<div class="row">
<div class="form-row">
<div class="form-group col-md-6">
<label>Time( Duration) in minutes</label>
<input type="number" class="form-control" name="test_duration" min="1"
oninput="validity.valid||(value='')" required>
</div>
</div>
</div>
<div class="row">
<div class="form-row">
<div class="form-group col-md-4">
<input type="button" value="Next" id="first_next" class="btn btn-primary btn-lg mb-10">
</div>
</div>
</div>
</form>
</div>
<script>
$(document).ready(function(){
$("#first_next").click(function(e){
var num_of_qu = $("#num_qu").val();
alert(num_of_qu);
});
});
</script>
{% endblock content %}
I have a dropdown selection and 'submit' button in the page. Some fields disappears upon specific dropdown selection. I can hide/show all other fields but except password field. Whenever I hide the password field with a jquery the submit button doesnot work.
following are my code files.
HTML template django
< script >
$(document).ready(function() {
$('#type').change(function(eventObject) {
if ($(this).val() == 'sercomm') {
$('.sample').show();
$('.sample_netip').show();
$('.sample_password').show();
$('.sample_username').hide();
} else {
$('.sample').show();
$('.sample_password').show();
$('.sample_netip').hide();
}
}).change();
});
<
/script>
<form class="form-horizontal" method="post" role="form">{% csrf_token %} {# dropdown#}
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Mode" %}</label>
<div class="col-sm-6">
<select name="type" class="form-control" id="type">
<option value="ex1" selected>{% trans "ex1" %}</option>
<option value="ex2">{% trans "ex2" %}</option>
</select>
</div>
</div>
{# end of dropdown#}
<div class="form-group sample">
<label class="col-sm-3 control-label">{% trans "Name" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="name" placeholder="{% trans " Name " %}" maxlength="20" id="name" required pattern="[a-zA-Z0-9\.\-_]+">
</div>
</div>
<div class="form-group sample">
<label class="col-sm-3 control-label">{% trans "Management Network IP Address" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="ipaddr" value="192.168.255.129" maxlength="20" required pattern="^(25[0-5]|2[0-4]\d|[0-1]?\d?[1-9]|[0-1]?[1-9][0])(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$">
</div>
</div>
<div class="form-group sample_netip">
<label class="col-sm-3 control-label">{% trans "Radio Network IP Address" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="netipaddr" value="192.168.255.129" maxlength="20" required pattern="^(25[0-5]|2[0-4]\d|[0-1]?\d?[1-9]|[0-1]?[1-9][0])(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$">
</div>
</div>
<div class="form-group sample_username">
<label class="col-sm-3 control-label">{% trans "User Name" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="username" value="" maxlength="48" required pattern="[a-zA-Z0-9\.\-_]+">
</div>
</div>
<div class="form-group sample_password">
<label class="col-sm-3 control-label">{% trans "Password" %}</label>
<div class="col-sm-6">
<input type="password" class="form-control" name="password" value="" maxlength="48" required pattern="[a-zA-Z0-9\.\-_]+">
</div>
</div>
<div class="form-group sample">
<label class="col-sm-3 control-label">{% trans "Description" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="description" value="" maxlength="48" pattern="[a-zA-Z0-9\.\-_ ]+">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
<button type="submit" class="btn btn-primary" name="create" value="1">{% trans "Create" %}</button>
</div>
</form>
forms.py goes here
import re
from django import forms
from django.utils.translation import ugettext_lazy as _
class BaseStationDetailsForm(forms.Form):
type = forms.ChoiceField(required=True, choices=(('nokia', 'nokia'), ('sercomm', 'sercomm')))
name = forms.SlugField(error_messages={'required': _('No base station name has been entered')}, max_length=20)
ipaddr = forms.IPAddressField(error_messages={'required': _('Invalid IP Address')})
netipaddr = forms.IPAddressField(error_messages={'required': _('Invalid IP Address')}) #test
username = forms.CharField(error_messages={'required': _('No user name has been entered')}, max_length=48)
password = forms.CharField(error_messages={'required': _('No password has been entered')}, max_length=48)
description = forms.CharField(required=False, max_length=48)
models.py
from django.db import models
class BaseStation(models.Model):
name = models.CharField(max_length=20)
address = models.IPAddressField()
ipaddress = models.IPAddressField() #tests
username = models.CharField(max_length=48)
password = models.CharField(max_length=48)
description = models.CharField(max_length=48, blank=True, null=True)
status = models.IntegerField(default=0)
def __unicode__(self):
return self.name
views.py (only the create (post) button is gives :
if 'create' in request.POST:
form = BaseStationDetailsForm(request.POST)
if form.is_valid():
data = form.cleaned_data
if basestations and data['name'] in basestation_names:
msg = _("Base Station with this name already exists")
errors.append(msg)
elif ip_addresses and data['ipaddr'] in ip_addresses:
msg = _("IP address " + data['ipaddr'] + " is already assigned to another Base Station")
errors.append(msg)
else:
_type = request.POST.get('type', '')
basestation = BaseStation(name=data['name'],
address=data['ipaddr'],
ipaddress=data['netipaddr'],
username=data['username'],
password=data['password'],
description=data['description'],
status='0')
# test
basestation.save()
return HttpResponseRedirect(request.get_full_path())
else:
for error_key in form.errors:
for error_msg in form.errors[error_key]:
errors.append(error_msg)
### other post button functions code deleted
return render_to_response('basestations.html', locals(), context_instance=RequestContext(request))
Example - I can show /hide username/description, the create button works. Only when password field is hidden, the button does not work.
When you are hiding the password field you also have to remove the required attribute with something like this
$('#password_field').removeAttr('required');
And then when you show the field add the required again so that the form does not submit without the password.
Your password field have attribute required. Which means that this field is required to submit the form.
To prevent this behavior, during form submission you need to have the following markup.
<div class="col-sm-6">
<input type="password" class="form-control" name="password" value="" maxlength="48" pattern="[a-zA-Z0-9\.\-_]+">
</div>
Mozilla Reference for HTML validations
I tried to follow answer here to do this in my code: How do I disable input field when certain select list value is picked but not working for me.
I have an HTML select field id 'TfL' with Yes/No answer, and next field 'TfLroad' is an input field. I want 'TfLroad' to load as disabled by default, then if 'TfL' changes from No to Yes, then 'TfLroad' should be enabled.
Whole page code below, JS at top of file, these two fields next to bottom, tx any suggestions!:
{% extends "base.jinja2" %}
{% block content %}
<script>
// value 0 for No answer to TfL road 1 for, in which case disabled, on change should
// enable TfLroad element by setting disabled = false, but not working yet!
document.getElementById("TfLroad").onload = function () {
document.getElementById("TfLroad").disabled = true;
}
document.getElementById('TfL').onchange = function () {
if(this.value = '0') {
document.getElementById("TfLroad").disabled = true;
}
else {
document.getElementById("TfLroad").disabled = false;
}
}
</script>
<h2 style="text-align:center">Add A 'Dummy' Street</h2>
<p>You can create a Dummy street here, which you will be able to search for in this application. This is to
demonstrate how a real Create & Update Process could work for this application, without corrupting the original
data. Dummy streets are indicated in search results.</p>
<form class="form-horizontal" action = "" method="post">
<fieldset>
<div class="form-group">
<div class="col-lg-6">
<label for="stname" class="control-label">Street Name</label>
<input class="form-control" id="stname" name="stname" pattern="^\S.{3,98}\S$"
title="Sorry, you must type from 5 to 100 characters, and no space at beginning or end."
placeholder="Full Street Name" required>
<!-- required attribute needed because empty string bypasses the pattern regex. -->
<span class="help-block">NB: No naughty word streets please, these will be deleted by admin!</span>
</div>
<!-- CR, CL, PR, 25, 16, 19, BE, KN, SC, TH, WA, WH -->
<div class="col-lg-3">
<label for="distr" class="control-label">Postal District</label>
<select class="form-control" id="distr" name="distr">
<option>Croydon (CR0, CR2, CR7 or CR9)</option>
<option>Coulsdon CR5</option>
<option>Purley CR8</option>
<option>London SE25</option>
<option>London SW16</option>
<option>Kenley CR8</option>
<option>South Croydon CR2</option>
<option>Thornton Heath CR7</option>
<option>Warlingham CR6</option>
<option>Whyteleafe CR3</option>
<option>Beckenham BR3</option>
</select>
<span class="help-block">NB: Original data uses postal district only, hence problem with several postcodes for Croydon.</span>
</div>
<div class="col-lg-3">
<label for="maint" class="control-label">Who looks after this street?</label>
<select class="form-control" id="maint" name="maint">
<option>Croydon Borough</option>
<option>Transport for London</option>
<option>Private Road</option>
</select>
</div>
</div>
<div class="form-group">
<h4 class="centre">Street Number Limits for this Street Section<br/><small>Please leave as None if all properties in this section have names</small></h4>
</div>
<div class="form-group">
<div class="col-lg-3">
<label for="onb" class="control-label">Odd Numbers From</label>
<input class="form-control" id="onb" name="onb" value="None" pattern="^\d*[13579]$|(None)" title="Odd Numbers only please with no spaces, or None">
<span class="help-block">e.g. '1' or '111'</span>
</div>
<div class="col-lg-3">
<label for="one" class="control-label">Odd Numbers To</label>
<input class="form-control" id="one" name="one" value="None" pattern="^\d*[13579]$|(None)" title="Odd Numbers only please with no spaces, or None">
<span class="help-block">e.g. '31' or '217'</span>
</div>
<div class="col-lg-3">
<label for="enb" class="control-label">Even Numbers From</label>
<input class="form-control" id="enb" name="enb" value="None" pattern="^\d*[02468]$|(None)" title="Even Numbers only please with no spaces, or None">
<span class="help-block">e.g. '2' or '110'</span>
</div>
<div class="col-lg-3">
<label for="ene" class="control-label">Even Numbers To</label>
<input class="form-control" id="ene" name="ene" value="None" pattern="^\d*[02468]$|^(None)$" title="Even Numbers only please with no spaces, or None">
<span class="help-block">e.g. '32' or '216'</span>
</div>
</div>
<div class="form-group">
<div class="col-lg-4">
<label for="rdclass" class="control-label">Road Class</label>
<select class="form-control" id="rdclass" name="rdclass">
<option>Unclassified</option>
<option>A Road</option>
<option>B Road</option>
<option>C Road</option>
</select>
<span class="help-block">Leave as Unclassified if in any doubt.</span>
</div>
<div class="col-lg-4">
<label for="length" class="control-label">Length of this Street Section (whole no. metres)</label>
<input class="form-control" id="length" name="length" value= 0 pattern="^[1-9][0-9]*$" title="Whole number of metres please, no spaces!" required>
</div>
<div class="col-lg-4">
<!-- JS here to put in A B C / disable depending on what selected in rdclass box -->
<label for="rdnum" class="control-label">Road Number</label>
<input class="form-control" id="rdnum" name="rdnum" pattern="^[ABC][1-9][0-9]*$|^(None)$" title="Must be None, or A, B or C followed by a whole number for the road class, no spaces!" value="None" required>
<span class="help-block">Only for A/B/C roads e.g. 'A232', 'C3241'</span>
</div>
</div>
<div class="form-group">
<div class="col-lg-3">
<label class="control-label left">Does one end of this street adjoin a TfL maintained street?</label>
<select class="form-control" id="TfL">
<option value="0">No</option>
<option value="1">Yes</option>
</select>
</div>
<div class="col-lg-4">
<!-- JS not working yet to disable only if no selected in rdclass box -->
<label class="control-label"><br/> Road Number of Adjoining TfL Road?</label>
<input class="form-control" pattern="^[ABC][1-9][0-9]*$|^(None)$"
title="Must be None, or A, B or C followed by a whole number, no spaces!" value="None" id="TfLroad" required>
<span class="help-block">E.g. 'A232', 'B2441'</span>
</div>
</div>
<div class="form-group">
<div class="centre">
<button type="reset" class="btn btn-default">Reset Form</button>
<button type="submit" class="btn btn-primary">Create Street</button>
</div>
</div>
</fieldset>
</form>
{% endblock %}
Instead of setting disabled through javascript you could add the disabled to the HTML input element:
<input class="form-control" disabled="disabled" .... />
Then in your javascript:
document.getElementById('TfL').onchange = function ()
{
if (this.value == '0')
{
document.getElementById("TfLroad").disabled = true;
}
else
{
document.getElementById("TfLroad").disabled = false;
}
}
There are several problems in the HTML/script you provided.
The <script> content is executing before the form fields exist (onload code isn't implemented the way you've done it.)
You haven't picked a default value for TfL
You haven't disabled TfLroad by default
You've got a typo in a comparison.
Fixing in order:
move the <script> to the bottom of the page and remove the onload function.
assuming you want No selected by default:
<select class="form-control" id="TfL">
<option value="0" selected>No</option>
<option value="1">Yes</option>
</select>
Add disabled attribute
<input class="form-control" pattern="^[ABC][1-9][0-9]*$|^(None)$" disabled
title="Must be None, or A, B or C followed by a whole number, no spaces!" value="None" id="TfLroad" required>
usie = instead of == (or ===):
if(this.value = '0') {
Should be
if(this.value === '0') {
(You could also rewrite the onchange handler):
document.getElementById('TfL').onchange = function () {
document.getElementById("TfLroad").disabled = (this.value === '0');
}
disabled is a Boolean attribute. You don't disable an element by setting its attribute to disabled=false. The browser checks if your element HAS a disabled property and doesn't care if its disabled=true, disabled=false, disabled=elephant. In order to "enable" your element you must completely remove the disabled attribute.
This should work:
document.getElementById('TfL').onchange = function () {
if(this.value == '0') {
document.getElementById("TfLroad").disabled = "elephant";
}
else {
document.getElementById("TfLroad").removeAttr("disabled");
}
}
Also when comparing two values use == and not =.
So the problem is load event does not work on all elements, it only supports the below HTML tags.
<body>, <frame>, <frameset>, <iframe>, <img>, <input type="image">,
<link>, <script> and <style>
Refer here to know more.
Also I have changed the logic for applying the initial disabled condition, please check it!
As an alternative you can watch for document.ready instead and then apply this change. Refer the below snippet.
var select = document.getElementById('TfL'), input = document.getElementById("TfLroad");
document.addEventListener("DOMContentLoaded", function(event) {
if (select.value === '0') {
input.disabled = true;
} else {
input.disabled = false;
}
});
select.onchange = function() {
if (this.value === '0') {
input.disabled = true;
} else {
input.disabled = false;
}
}
<h2 style="text-align:center">Add A 'Dummy' Street</h2>
<p>You can create a Dummy street here, which you will be able to search for in this application. This is to demonstrate how a real Create & Update Process could work for this application, without corrupting the original data. Dummy streets are indicated
in search results.</p>
<form class="form-horizontal" action="" method="post">
<fieldset>
<div class="form-group">
<div class="col-lg-6">
<label for="stname" class="control-label">Street Name</label>
<input class="form-control" id="stname" name="stname" pattern="^\S.{3,98}\S$" title="Sorry, you must type from 5 to 100 characters, and no space at beginning or end." placeholder="Full Street Name" required>
<!-- required attribute needed because empty string bypasses the pattern regex. -->
<span class="help-block">NB: No naughty word streets please, these will be deleted by admin!</span>
</div>
<!-- CR, CL, PR, 25, 16, 19, BE, KN, SC, TH, WA, WH -->
<div class="col-lg-3">
<label for="distr" class="control-label">Postal District</label>
<select class="form-control" id="distr" name="distr">
<option>Croydon (CR0, CR2, CR7 or CR9)</option>
<option>Coulsdon CR5</option>
<option>Purley CR8</option>
<option>London SE25</option>
<option>London SW16</option>
<option>Kenley CR8</option>
<option>South Croydon CR2</option>
<option>Thornton Heath CR7</option>
<option>Warlingham CR6</option>
<option>Whyteleafe CR3</option>
<option>Beckenham BR3</option>
</select>
<span class="help-block">NB: Original data uses postal district only, hence problem with several postcodes for Croydon.</span>
</div>
<div class="col-lg-3">
<label for="maint" class="control-label">Who looks after this street?</label>
<select class="form-control" id="maint" name="maint">
<option>Croydon Borough</option>
<option>Transport for London</option>
<option>Private Road</option>
</select>
</div>
</div>
<div class="form-group">
<h4 class="centre">Street Number Limits for this Street Section<br/><small>Please leave as None if all properties in this section have names</small></h4>
</div>
<div class="form-group">
<div class="col-lg-3">
<label for="onb" class="control-label">Odd Numbers From</label>
<input class="form-control" id="onb" name="onb" value="None" pattern="^\d*[13579]$|(None)" title="Odd Numbers only please with no spaces, or None">
<span class="help-block">e.g. '1' or '111'</span>
</div>
<div class="col-lg-3">
<label for="one" class="control-label">Odd Numbers To</label>
<input class="form-control" id="one" name="one" value="None" pattern="^\d*[13579]$|(None)" title="Odd Numbers only please with no spaces, or None">
<span class="help-block">e.g. '31' or '217'</span>
</div>
<div class="col-lg-3">
<label for="enb" class="control-label">Even Numbers From</label>
<input class="form-control" id="enb" name="enb" value="None" pattern="^\d*[02468]$|(None)" title="Even Numbers only please with no spaces, or None">
<span class="help-block">e.g. '2' or '110'</span>
</div>
<div class="col-lg-3">
<label for="ene" class="control-label">Even Numbers To</label>
<input class="form-control" id="ene" name="ene" value="None" pattern="^\d*[02468]$|^(None)$" title="Even Numbers only please with no spaces, or None">
<span class="help-block">e.g. '32' or '216'</span>
</div>
</div>
<div class="form-group">
<div class="col-lg-4">
<label for="rdclass" class="control-label">Road Class</label>
<select class="form-control" id="rdclass" name="rdclass">
<option>Unclassified</option>
<option>A Road</option>
<option>B Road</option>
<option>C Road</option>
</select>
<span class="help-block">Leave as Unclassified if in any doubt.</span>
</div>
<div class="col-lg-4">
<label for="length" class="control-label">Length of this Street Section (whole no. metres)</label>
<input class="form-control" id="length" name="length" value=0 pattern="^[1-9][0-9]*$" title="Whole number of metres please, no spaces!" required>
</div>
<div class="col-lg-4">
<!-- JS here to put in A B C / disable depending on what selected in rdclass box -->
<label for="rdnum" class="control-label">Road Number</label>
<input class="form-control" id="rdnum" name="rdnum" pattern="^[ABC][1-9][0-9]*$|^(None)$" title="Must be None, or A, B or C followed by a whole number for the road class, no spaces!" value="None" required>
<span class="help-block">Only for A/B/C roads e.g. 'A232', 'C3241'</span>
</div>
</div>
<div class="form-group">
<div class="col-lg-3">
<label class="control-label left">Does one end of this street adjoin a TfL maintained street?</label>
<select class="form-control" id="TfL">
<option value="0">No</option>
<option value="1">Yes</option>
</select>
</div>
<div class="col-lg-4">
<!-- JS not working yet to disable only if no selected in rdclass box -->
<label class="control-label"><br/> Road Number of Adjoining TfL Road?</label>
<input class="form-control" pattern="^[ABC][1-9][0-9]*$|^(None)$" title="Must be None, or A, B or C followed by a whole number, no spaces!" value="None" id="TfLroad" required>
<span class="help-block">E.g. 'A232', 'B2441'</span>
</div>
</div>
<div class="form-group">
<div class="centre">
<button type="reset" class="btn btn-default">Reset Form</button>
<button type="submit" class="btn btn-primary">Create Street</button>
</div>
</div>
</fieldset>
</form>
So I have a create announcement form and then an edit form for each announcement and each form has its own datepicker. My function for controlling the datepicker is:
$(function() {
$( ".datepicker" ).datepicker({
changeMonth: true,
changeYear: true,
});
});
Initially my issue was that using the datepicker in one of the edit forms would change the field in the create form since the ids were the same. I got around this by adding ids (in my forms.py) like so:
end_date = forms.DateField(label='Expires', widget=forms.TextInput(attrs={'class':'datepicker form-control', 'id':'end_date_create'}))
and
end_date = forms.DateField(label='Expires', widget=forms.TextInput(attrs={'class':'datepicker form-control', 'id':'end_date_edit'}))
to my createAnnouncement and EditAnnouncement forms. But since I have multiple edit forms per page, I still have the same issue where using the datepicker on any edit form changes the field of only the top edit form. I am using django widget tweaks to render my forms so it automatically generates HTML and ids and classes and everything. Each edit form is in a div with a unique id, but the form fields themselves are named the same thing across all the forms. Does anyone know how I could generate unique ids for my form fields with django widget tweaks? Or maybe there is some javascript or something I could add to my datepicker function that tells the datepicker to change the value of the field that is in the same div?
EDIT: My template looks like this:
{% if boardAnnouncements %}
<h3>Announcements</h3>
<div class="container" style="margin: 0px; padding: 0px;">
<ul>
{% for announcement in boardAnnouncements %}
<div class="row" style="padding-bottom: 10px;">
<li>
<div class="col-md-6">
<!-- display announcement content -->
</div>
<div class="col-md-6">
<!-- edit button calls javascript function to hide/unhide div with edit form in it -->
<i class="fa fa-pencil" aria-hidden="true"></i> Edit
</div>
</div>
<!-- each div gets unique id that corresponds to announcemt id -->
<div id="editann-{{announcement.id}}" class="hidden">
<form role="form" action="/editannouncement/{{announcement.id}}/" method="post">
<!-- display edit form with django widget tweaks -->
{% csrf_token %}
{% for field in editAnnouncement %}
{% if field.errors %}
<div class="form-group has-error">
<label class="col-sm-2 control-label" for="id_{{ field.name }}">
{{ field.label }}</label>
<div class="col-sm-10">
{{ field }}
<span class="help-block">
{% for error in field.errors %}
{{ error }}
{% endfor %}
</span>
</div>
</div>
{% else %}
<div class="form-group">
<label class="col-sm-2 control-label" for="id_{{ field.name }}">{{ field.label }}</label>
<div class="col-sm-10">
{{ field }}
{% if field.help_text %}
<p class="help-block"><small>{{ field.help_text }}</small></p>
{% endif %}
</div>
</div>
{% endif %}
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" name="edit_announcement" class="btn btn-primary">Save</button><br><br>
</div>
</div>
</form>
</li>
</div>
{% endfor %}
</ul>
</div>
{% endif %}
<div>
And the generated HTML for the edit forms is:
<div id="editann-1" class="unhidden">
<form class="ng-pristine ng-valid" role="form" action="/editannouncement/1/" method="post">
<input name="csrfmiddlewaretoken" value="AbTEZYmK1RF9yeom1C34IFFCj3EBrOD3" type="hidden">
<div class="form-group">
<label class="col-sm-2 control-label" for="id_description">Edit Description</label>
<div class="col-sm-10">
<textarea class="form-control" cols="40" id="id_description" name="description" rows="10"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="id_end_date">Expires</label>
<div class="col-sm-10">
<input class="datepicker form-control hasDatepicker" id="end_date_edit" name="end_date" type="text">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" name="edit_announcement" class="btn btn-primary">Save</button><br><br>
</div>
</div>
</form>
</div>
<div id="editann-2" class="unhidden">
<form class="ng-pristine ng-valid" role="form" action="/editannouncement/2/" method="post">
<input name="csrfmiddlewaretoken" value="AbTEZYmK1RF9yeom1C34IFFCj3EBrOD3" type="hidden">
<div class="form-group">
<label class="col-sm-2 control-label" for="id_description">Edit Description</label>
<div class="col-sm-10">
<textarea class="form-control" cols="40" id="id_description" name="description" rows="10"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="id_end_date">Expires</label>
<div class="col-sm-10">
<input class="datepicker form-control hasDatepicker" id="end_date_edit" name="end_date" type="text">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" name="edit_announcement" class="btn btn-primary">Save</button><br><br>
</div>
</div>
</form>
</div>
So to clarify each editann-# div has an edit form in it (and each edit form has a datepicker). Right now since the all the edit form "Expire" fields have id id_end_date the datepicker changes the value of the first edit form, no matter which datepicker I am using.
I came up with a solution involving some javascript and jQuery.
function unhide_announcement(divID, ID) {
var item = document.getElementById(divID);
if (item) {
/* hide/unhide div */
item.className=(item.className=='hidden')?'unhidden':'hidden';
/* give each end_date field a unique ID */
var newID = 'id_end_date' + ID;
item.querySelector('#id_end_date').id = newID;
/* datepicker functionality */
$(function() {
$( '#'+newID ).datepicker({
changeMonth: true,
changeYear: true,
});
})
}
}
Since each edit announcement form is in a unique div, I get that div first and then within the div there is only 1 edit announcement form so I change that id from id_end_date to id_end_date1 or whichever announcement id it is associated with. And then I changed the jQuery datepicker function I had to select by id instead of by class and it worked. So when I call it in my template it looks like this:
Edit
<div id="editann-{{announcement.id}}" class="hidden">
<!-- edit announcement form -->
<form>
...
</form>
</div>
You shouldn't have two of the same id on one page. ID's must be unique. That's what is creating the error.
To add more than one form on the page, you should use Formsets which will automatically make sure your id's are unique.
By removing the id attribute from your code I was able to make the datepickers work. See this working fiddle.
Note that I had to remove hasDatepicker class from the html you pasted as that's actually inserted by the datepicker function - if you leave it in it will create a conflict and the datepicker won't show up.