I'm working on a quiz app and want to generate a number of input fields representing the answers based on the value that the user types.
I'm using a button named "create" to do that Using JavaScript, but when clicking the button it submits the form.
Please Check the two images below.
Input
Output
HTML Code
{% load static %}
{% block body %}
<button class="btn btn-primary new">Add a question</button>
<form class="question" method="POST" style="display: none">
{% csrf_token %}
<div class="form-group">
<label for="exampleInputEmail1">Title</label>
<input type="text" class="form-control" id="title" placeholder="Question title">
</div>
<div class="form-group" id="answers_num">
<label for="exampleInputPassword1">Number of answers</label>
<input type="number" class="form-control" id="ans_number">
<button class="create_answers">Create</button>
</div>
<div class="form-group">
{% comment %} Generated input fields {% endcomment %}
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% block script %}
<script src="{% static 'mcq/index.js' %}"></script>
{% endblock %}
{% endblock %}```
JS code
document.querySelector(".new").addEventListener("click", ()=> {
document.querySelector(".question").style.display = 'block';
document.querySelector("#create_answers").addEventListener("click", ()=> {
answers = this.value;
console.log(answers);
// Create input fields
for (let i = 0; i < answers; i++) {
input = document.createElement("input");
input.classList.add('form-control');
answersDiv = document.querySelector("#answers").appendChild(input);
}
})
})```
You need to explicitly set the type of the button, like
<button class="create_answers" type="button">Create</button>
in order to avoid submitting the form upon click.
Related
I'm trying to prevent/allow the user from clicking a button depending on whether a key is present in the request.session data.
It works for blocking it, but once the key is added to the session, that isn't reflected on the webpage/template and the key remains blocked. I presume I'll have to do this in JS but I'm not sure how to approach it. Any ideas?
Thanks
{% if choices not in request.session %}
<form class="submit-form" action="{% url 'search' %}" method="post" onsubmit="return false;">
{% csrf_token %}
<input type="submit" class="show-more-button cunt" style="margin-left: 5px" name="mybtn"
value="Search" data-bs-toggle="popover"
data-bs-placement="right" data-bs-trigger="focus"
data-bs-content="Please select one or more ingredient">
</form>
{% else %}
<form action="{% url 'search' %}" method="post">
{% csrf_token %}
<input type="submit" class="show-more-button" style="margin-left: 5px" name="mybtn"
value="Search">
</form>
{% endif %}
if request.POST.get('button_color') == 'green':
selected_ingredients = request.session.get('choices', [])
selected_ingredients.insert(len(selected_ingredients), ingredients_name)
request.session['choices'] = selected_ingredients
request.session.modified = True
Based on the following image, I am trying to make the fields category and current points non-editable when the status of the task is Finalized or Cancelled, otherwise the fields should be editable.
Below is the code from my html file.
{% extends "base.html" %} {% load widget_tweaks %}
{% block content %}
<div id="form-group">
<form method="POST" action="." enctype="multipart/form-data">
{% csrf_token %}
<label>Select your category</label>
{{ form.category|add_class:"card" }}
<label>What's the status of the task?</label>
{{ form.status|add_class:"card" }}
<label>Current points:</label>
{{ form.points|add_class:"card" }}
<label>Finalized date:</label>
{{ form.ending_date|add_class:"card" }}
<button type="submit" class="btn btn-success">Send</button>
</form>
</div>
Below is the code from my forms.py file.
class TaskModelForm(forms.ModelForm):
class Meta:
model= Task
fields = ['category', 'status', 'points']
def __init__(self, *args, **kwargs):
super(TaskModelForm, self).__init__(*args, **kwargs)
self.fields['status'].required = False
self.fields['points'].required = False
When I want to edit the contents of this form I need to verify if the status is Finalized, so the fields are non-editable, otherwise the fields should be editable and I am thinking something about:
{% extends "base.html" %} {% load widget_tweaks %}
{% block content %}
{% if form.status.value == 'Active' %} <!--make the fields editable -->
<div id="form-group">
<form method="POST" action="." enctype="multipart/form-data">
{% csrf_token %}
<label>Select your category</label>
{{ form.category|add_class:"card" }}
...
<button type="submit" class="btn btn-success">Send</button>
</form>
</div>
{% endif %}
{% if form.status.value == 'Finalized' %} <!--make the fields non-editable -->
<div id="form-group">
<form method="POST" action="." enctype="multipart/form-data">
{% csrf_token %}
<label>Select your category</label>
{{ form.category|add_class:"card" }}
...
<button type="submit" class="btn btn-success">Send</button>
</form>
</div>
{% endif %}
However, I believe my approach might not work because this could be a more front-end problem rather than back-end one (just a guess). Can you point me out to the right direction to solve this problem?
Since the status is something that the user selects, you can't address your requirement with Python (Django) running on the server. You have to address it with a JavaScript running in the web page that displays the form. Something like this will definitely do the trick.
{% extends "base.html" %} {% load widget_tweaks %}
{% block content %}
<body onload="makeReadOnly();">
<div id="form-group">
<form method="POST" action="." enctype="multipart/form-data">
{% csrf_token %}
<div class="tweet-composer">
<label>Insert your task</label>
{{ form.task|add_class:"card js-keeper-editor" }}
</div>
<label>Select your category</label>
{{ form.category|add_class:"card" }}
<label>Current points:</label>
{{ form.points|add_class:"card" }}
<button type="submit" class="btn btn-success">Send</button>
</form>
</div>
</body>
{% endblock content %}
<script type="text/javascript">
{% block jquery %}
function makeReadOnly()
{
if (document.getElementById('id_status').value == 'Finalized'){
document.getElementById('id_task').readOnly=true;
document.getElementById('id_category').readOnly=true;
}else if (document.getElementById('id_status').value == 'Active'){
document.getElementById('id_task').readOnly=true;
document.getElementById('id_category').readOnly=false;
}
}
document.getElementById('id_status').addEventListener('change', makeReadOnly);
{% endblock %}
</script>
With the "view page source" you can see the HTML structure that Django generates out of your form, so that you can identify the right bits with JQuery selectors. Alternatively you can do
f = SomethingForm()
f.as_p()
in the ./manage.py shell console.
At the Django end, you may need custom form validation to handle the inter-dependency between the value of status and whether the other fields are required or not.
I have two forms on one page, each with its own submit button. With JS script I can dynamically add a new formset for each of the two form. I am faced with a situation where I can add as many new forms as I want for the form that is displayed first on the page and all are saved. For the second forms list, only the first form from the formset list is saved.
template.html
<form method="post" action="">{% csrf_token %}
{{ formset_planguage.management_form }}
<div id="form_set_lang">
{% for form in formset_planguage.forms %}
{{form.non_field_errors}}
{{form.errors}}
<table class='no_error'>
{{ form }}
</table>
{% endfor %}
</div>
<input type="button" value="Add More" id="add_more_lang">
<div id="empty_form_lang" style="display:none">
<table class='no_error'>
{{ formset_planguage.empty_form }}
</table>
</div>
<input class='btn btn-primary' type="submit" name="language" value="Submit"/>
</form>
<form method="post" action="">{% csrf_token %}
{{ formset_framework.management_form }}
<div id="form_set_framework">
{% for form in formset_framework.forms %}
{{form.non_field_errors}}
{{form.errors}}
<table class='no_error'>
{{ form }}
</table>
{% endfor %}
</div>
<input type="button" value="Add More" id="add_more_framework">
<div id="empty_form_framework" style="display:none">
<table class='no_error'>
{{ formset_framework.empty_form }}
</table>
</div>
<input class='btn btn-primary' type="submit" name="framework" value="Submit"/>
</form>
<script>
$('#add_more_framework').click(function() {
var form_idx = $('#id_form-TOTAL_FORMS').val();
$('#form_set_framework').append($('#empty_form_framework').html().replace(/__prefix__/g, form_idx));
$('#id_form-TOTAL_FORMS').val(parseInt(form_idx) + 1);
});
</script>
<script>
$('#add_more_lang').click(function() {
var form_idx = $('#id_form-TOTAL_FORMS').val();
$('#form_set_lang').append($('#empty_form_lang').html().replace(/__prefix__/g, form_idx));
$('#id_form-TOTAL_FORMS').val(parseInt(form_idx) + 1);
});
</script>
Your two forms are like <form method="post" action=""> so the destination is always the same page, so Django will handle both forms the same way. If in your page you handle in the POST the values of the first form, the second will be handled like it's the first form.
The best solution is to send one "big" form with all your fields named differently in the first "group" and the second "group", and read only either the first "group" or if it's empty, the second "group".
The other solution is to send the second form to a different url.
I have three radio buttons.. each radio buttons on click have an independent form that appears. I need to remove form from DOM when i click on a radio button. and there are a third one not ready yet. When i click on the first radio button only its form appears, the other two are removed from DOM. Same for other.
I don't have a good idea about JavaScript.
Html:
<div class="page-header">
<h1>Backtesting{% if form.instance.pk %}: {{form.instance.title}} {% endif %}</h1>
</div>
<div class="row">
<div class='col-md-9'>
<form action="{% url "backtest" %}" method='POST' role='form' id='form'>
{% csrf_token %}
<div id="tabs">
<input type="radio" name="tabs" value="first" id="toggle-tab1" checked="checked" />
<label for="toggle-tab1">Long</label>
<input type="radio" name="tabs" value="second" id="toggle-tab2" />
<label for="toggle-tab2">Short</label>
<input type="radio" name="tabs" value="third" id="toggle-tab3" />
<label for="toggle-tab3">Long and Short</label>
<div id="tab1" class="tab" >
{% include 'tags/parameters_form.html' %}
<br />
{% if user.is_authenticated %}
<input type='submit' id='run' value='Run' class='btn btn-default'>
{% if user.profile.is_active %}
Name: {{ form.title }} <input type='submit' name='save' value='Save' class='btn btn-default'>
{% else %}
<p>
Expired account! you need to reactivate in order to save parameters.
</p>
{% endif %}
{% else %}
Please login in order to Run backtesting!
</br>
Our system needs your email in order to notify you once one or more of your simulations are done. This is a safer way for you to keep track of your previous simulations (/jobs).
{% endif %}
</div>
<div id="tab2" class="tab" >
{% include 'tags/parameters_backtest_form.html' %}
<br />
{% if user.is_authenticated %}
<input type='submit' id='run' value='Run' class='btn btn-default'>
{% if user.profile.is_active %}
Name: {{ form.title }} <input type='submit' name='save' value='Save' class='btn btn-default'>
{% else %}
<p>
Expired account! you need to reactivate in order to save parameters.
</p>
{% endif %}
{% else %}
Please login in order to Run backtesting!
</br>
Our system needs your email in order to notify you once one or more of your simulations are done. This is a safer way for you to keep track of your previous simulations (/jobs).
{% endif %}
</div>
</div>
</form>
</div>
</div>
{% endblock %}
<form action="{% url "backtest" %}" method='POST' role='form' id='form'>
{% csrf_token %}
<div id="tabs">
<input type="radio" name="tabs" value="first" id="toggle-tab1" checked="checked" />
<label for="toggle-tab1">Long</label>
<input type="radio" name="tabs" value="second" id="toggle-tab2" />
<label for="toggle-tab2">Short</label>
<input type="radio" name="tabs" value="third" id="toggle-tab3" />
<label for="toggle-tab3">Long and Short</label>
<div id="tab1" class="tab" >
<!-- first form will show when page load -->
<fieldset id="first" class="toggle">
{% include 'tags/parameters_form.html' %}
</fieldset>
<fieldset disabled id="second" class="toggle">
{% include 'tags/parameters_form.html' %}
</fieldset>
<fieldset disabled id="third" class="toggle">
{% include 'tags/parameters_form.html' %}
</fieldset>
.....
Js
$('[name="tabs"]').click(function(){
$('.toggle').prop("disabled", true);
var val = $(this).val()
$('#'+val).prop('disabled', false);
});
When you add disabled attr in fieldset then fieldset inner input field data will not post in form that means field will not work in fieldset tag if it have disabled attribute. So you can show specific form in each condition and add attribute disable in fieldset tag that inner field data will not post.
Read about https://www.w3schools.com/tags/att_fieldset_disabled.asp
If you cannot change DOM elements and add a class there my answer would be to attach a event listener to each of the buttons:
'use strict';
var button1 = document.getElementById('toggle-tab1'),
button2 = document.getElementById('toggle-tab2'),
button3 = document.getElementById('toggle-tab3');
button1.addEventListener('click', function () {
// Code that takes it away (hide DOM elements or whatever you need)
});
On a side note a better approach would be to add a function to all of the radio inputs and then based on the ID or value of the input radio you can alter the behavior:
<input type="radio" name="tabs" onclick="handleClick(this)" value="first" id="toggle-tab1" checked="checked" />
Then you can have a function:
function handleClick (e) {
if (e.id == 'toggle-tab1') {
// Code that takes it away (hide DOM elements or whatever you need)
}
};
function onclick(e){
var tab = document.getElementById('toggle-tab1');
tab.style.visibility = "hidden";
}
button1.addEventListener('click', onclick(e))
This should do the trick!
Problem is resolved with :
<input type="radio" name="tabs" value="first" id="toggle-tab1" {% if strategy == 'l' %} checked="checked"{% endif %} />
<label for="toggle-tab1">Long</label>
<input type="radio" name="tabs" value="second" id="toggle-tab2" {% if strategy == 's' %} checked="checked" {% endif %} />
<label for="toggle-tab2">Short</label>
<div id="tab1" class="tab" >
<form action="{% url "backtest" %}" method='POST' role='form' id='form'>
{% csrf_token %}
<input type="hidden" name="tabs" value="first" id="toggle-tab1" checked="checked" />
When I try to use the below code with jfiddle, I comment out the jinja and the buttons hide as expected, but in the browser, the input buttons don't hide
{% extends "layout.html" %}
{% block body %}
<div>
{% if session.logged_in %}
<form action="{{ url_for('add_entry') }}" method=post class=add-entry>
<dl>
<dt>Stock Ticker:
<dd><input type=text size=30 name=stockname>
<dt>Date:
<dd><input id="datePicker" type="date" name='start_date'>
<dd><input type=submit value=Add>
</dl>
</form>
{% endif %}
</div>
<div>
<form action="{{ url_for('edit_entry') }}" method=post class=edit-entry>
<table class="entries">
<tr>
<th>stock ticker</th>
<th>date bought</th>
<th> Edit</th>
</tr>
{% for entry in entries %}
<tr>
<td><h2>{{ entry.stockname }}</h2></td>
<td>{{ entry.start_date|safe }}</td>
<td>
<input type="hidden" name="name" value="Edit"/>
<input class="show" type="button" id="edit-button" value="Edit"/>
<input class="hide" type="button" id="cancel-button" value="Cancel Changes"/>
<input class="hide" type="submit" id="save-button" value="Save Changes"/>
</td>
</tr>
{% else %}
<em>Unbelievable. No entries here so far</em>
{% endfor %}
</table>
</form>
</div>
{% endblock %}
<script>
$(document).ready( function() {
var now = new Date();
var day = ("0" + now.getDate()).slice(-2);
var month = ("0" + (now.getMonth() + 1)).slice(-2);
var today = now.getFullYear()+"-"+(month)+"-"+(day) ;
$('#datePicker').val(today);
$(".hide").hide();
});
</script>
and layout.html consists of...
<!doctype html>
<title>Flaskr</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<div class=page>
<h1>Flaskr</h1>
<div class=metanav>
{% if not session.logged_in %}
log in
{% else %}
log out
{% endif %}
</div>
{% for message in get_flashed_messages() %}
<div class=flash>{{ message }}</div>
{% endfor %}
{% block body %}{% endblock %}
</div>
Fiddle: http://jsfiddle.net/5ZNTf/
You are defining lots of
<input type="submit" id="save-button" value="Save Changes"/>
in your for loop, so you have multiple input tags with the same id on the page, thus it does not work. Try giving the inputs a class instead.
Use class instead of id for your input elements.
<input type="hidden" class="name" value="Edit"/>
<input type="button" class="edit-button" value="Edit"/>
<input type="button" class="hide" value="Cancel Changes"/>
<input type="submit" class="hide" value="Save Changes"/>
Change the selector to use class.
$("input[class=hide]").hide();
Try this: http://jsfiddle.net/5ZNTf/1/
Id's need t be unique. If you would like to hide multiple elements with the same name use a class.
<button class="hide">Cancel</button>
<button class="hide">Save</button>
Then add a css class to hide them. It's more reliable IMO.
.hide {
display: none;
}
The issue had to do with localhost not property reading in jquery -_-
"//url" instead of "http://" or "https://" only works remotely