How to always get new checkboxes array, every time a different button is clicked - javascript

I'm developing an app about quizzes.
IMG1: [The added comments in this picture applies for the IMG2 too]
IMG2:
Description:
[IMG1] When one or more .js-answer-check checkbox are checked, I save the values in a js array. Then, when the #save-response button is clicked, the respective array is send to the server, to be saved in the db.
[IMG2] Then I click another question of the quiz, identified by .quiz-questions class, and when one or more .js-answer-check checkboxes of this new question are checked, the values are saved in the same js array.
The problem is that the previous checkboxes values, from the previous answers, are still present in the array, due to that answers.push(answerID).
How can I only grab the values of the respective question answers in the array each time a .quiz-questions button is clicked?
Expected values:
clicking the checkbox with label "2" in the first question => array should be [ 2 ] (the data-id="2" attribute in that checkbox)
clicking the checkboxes with label "1+3" and "8/2" in the second question => array should be [4, 5] as those checkboxes have data-id="4" and data-id="5" attributes.
Actual result: [2, 4, 5]
I tried out this code:
//if one|more options are checked...
var answers = [];
$(document).on('click', '.js-answer-check', function(){
if ($(this).is(':checked')){
var answerID = $(this).data('id');
answers.push(answerID);
} else {
var removeItem = $(this).data('id');
answers = $.grep(answers, function(value){
return value != removeItem;
});
}
});
$('#save-response').on('click', function(e){
e.preventDefault();
$.ajax({
method: 'POST',
url: Routing.generate('save_answer'),
data: { answers: answers },
success: function(resp) {
if (resp.success) {
var answersBack = resp.answers;
for (var ans in answersBack) {
console.log('answerID = ', answersBack[ans]);
}
}
//answers = [];
}
});
});
And I thought that if I do answers = [] will reset the initial array, but it didn't.
Any help is welcomed. Thanks.
LATER EDIT
<div class="row margin-top-ten">
<div class="col-6">
<input type="hidden" id="quiz-id" data-quiz="{{ quiz.id }}"/>
<div class="row question-content">{# the content (question-text + checkboxes) is coming from an AJAX request because I need to present everytime a new content based on `quiz-questions` buttons #}
</div>
</div>
</row>
<div class="row margin-top-ten">
<div class="col-12">
<button class="btn btn-primary btn-sm" type="button" id="save-response">Salveaza</button>
</div>
</div>
<div class="row margin-top-fifty">
<div class="col-12">
{% set i = 1 %}
<p>Navigator intrebari:</p>
{% for question in quiz.questions %}
<a href="" class="btn btn-info btn-sm quiz-question"
data-id="{{ question.id }}" data-quiz="{{ quiz.id }}">
{{ i }}
</a>
{% set i = i + 1 %}
{% endfor %}
</div>
</div>
The AJAX request for bringing new content for each quiz-questions buttons is:
<div class="col-12">
<div class="row">
<div class="col-12 question-text" data-question="{{ question.id }}">{{ question.content|raw }}</div>
</div>
<div class="row">
{% for answer in question.answers %}
<div class="col-12 question-answers">
<span style="display: inline-block">
<label for="">
<input type="checkbox" name="user-responses[]" class="js-answer-check" data-question="{{ question.id }}" data-id="{{ answer.id }}">
</label>
</span>
<span style="display:inline-block">{{ answer.answer|raw }}</span>
</div>
{% endfor %}
</div>
</div>
The save_answer php functionality is just returning the sent-data, for debug purposes. Nothing fancy.

Related

Decrement/increment for qty and the value field

I am trying to create a cart page with the ability to use the add or minus buttons to decrement or increment the value of the input but the eventlisteners don't seem to be working and I have tried many different solutions online for this and get it to work properly.
{% extends "base.min.html" %}
{% block body_block %}
{% load static %}
<div class='container'>
<a class='back-link' href="/"> Back to Catalog</a>
<h1 class='cart-h1'>Cart </h1>
<div class='cart'>
<div class='requests'>
<div class='request'>
<img src='https://developers.elementor.com/docs/assets/img/elementor-placeholder-image.png' alt='request image'>
<div class='request-info'>
<p class='request-name'>Request: {{ requestName }}</p>
<p class='request-details'>Details: {{ requestDetails }}</p>
<p class='request-qty'>Qty: {{ requestQty }}
<div class='qty-container'>
<input type='button' value='+' class='qtyplus' id='plus' field='quantity' />
<input type='text' name='quantity' value='0' class='qty' id='inputQty' />
<input type='button' value='-' class='qtyminus' id='minus' field='quantity' />
</div>
</p>
<p class='qty-remove'></p>
<span class='remove'>Remove</span>
</div>
</div>
</div>
</div>
</div>
</br>
<div class='hidden-container'>
<p>Checkout Confirmation #: {{confirmNum}}</p>
</div>
<script type="module" src="{% static '\js\supplyshop\pageload\RequestManagementLoad.min.js' %} " type ="text/javascript"></script>
{% endblock %}
const plusBtn = document.querySelector('#plus')
const minusBtn = document.querySelector('#minus')
const inputQty = document.querySelector('#inputQty')
// increment/decrement value on input field
// add eventlisteners on +/- buttons to update the value field
plusBtn.addEventListener('click', e => {
e.preventDefault()
inputQty.value = parseInt(inputQty.value) + 1
})
minusBtn.addEventListener('click', e => {
e.preventDefault()
if (inputQty.value <= 0) {
inputQty.value = 0
}
inputQty.value = parseInt(inputQty.value) - 1
})
I tried using incrementing/decrementing the value of the input field which holds the quantity value. I've also tried using the onclick function in html and making a function that does the same thing in that but I may be going about it the wrong way as nothing is working properly. The behavior I am expecting is to click the plus or minus button and the number in the middle (input field) will increase by one or decrease by one if the add/minus button is clicked. I also want to make sure the value can't go below 0.
1 -
check with this:
minusBtn.addEventListener('click', e => {
e.preventDefault()
if (inputQty.value <= 0) {
inputQty.value = 0
}else{
inputQty.value = parseInt(inputQty.value) - 1
}
})

How do you implement input( or form) dependent on a select menu(drop down list)?

I'm working on grading system and I'm currently working on the form that's deals with the user entering the students results now the form I have, has 2 drop-down list(classroom, students) that are dependent. The issue and where I'm stuck is
When the user select the classroom the second drop-down menu will only show the students in that class, I have already figure that out..the issue is I want the input fields for how much subject the student is doing to appear so that the user can enter the grades for each subject specific to that student in the class
Eg if I select classroom 1b and selected student Mary.. if Mary is doing 5 subjects then 5 input field should appear so that I can enter the mark for the subjects
Link with a video showing what I'm talking about video showing an examplehttps://drive.google.com/file/d/11FoCZyOBVdUhTcvCqA1Ke0fEgRmMVC-G/view?usp=drivesdk
Models.py
Class Classroom(models.Models): name = models.charfield()
Class marks (models.Models): classroom = models.foreignkey(Classroom) Grade = models.Floatfield()
Html form
<div class="container-fluid">
<form id="result-form" method="post">
{% csrf_token %}
<!-- Modal -->
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel"> {% block modal-title%} Add Result {% endblock%}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12" id="msg8" style="font-size: 2rem; color:rgb(255, 144, 47)"></div>
<div class="col-md-12 form-group p-2">
<label class="form-label">Class Name</label>
{% render_field form.room class+="form-control" %}
</div>
<div class="col-md-12 form-group p-2">
<label class="form-label">Exam Name</label>
{% render_field form.exam class+="form-control" %}
</div>
<div class="col-md-12 form-group p-2">
<label class="form-label">Student</label>
{% render_field form.student class+="form-control select2" %}
</div>
<div class="hidden" id="subject-fields"></div>
<div class="form-group mb-3 pt-2">
<button type="button" id="resBtn" class="btn btn-info" title="Add">Submit</button>
</div>
</div>
</div>
</form>
</div>
{% block script%}
{% endblock%
script
$(document).on('click', '#submit-btn', function(event){
var response_data = []
var subject_name= $('.course');
var subject_objs = $('.subject_id');
for(i=0;i<subject_name.length;i++){
var subject_id = $(subject_objs[i]).find('input').val();
var grade_input = {
"Marks": subject_id,
}
response_data.push(grade_input);
}
$.ajax({
type: "POST",
url: "{% url 'marks' %}",
data: response_data,
success: function(response){
alert("Success");
}
});
});
This is how your view should look like.
def question_choice_view(request):
if request.method == "POST":
question_choice_data = request.POST['data']
I am not a jQuery User. As far as i can see i would put a eventlistener on the student form via .addEventListener('change', (event)See here. This would fire a function every time something changes on the select option. With that you could also collect the selected option values of the classroom and student name and make a request to get the subject names for the chosen student. After successful response i would insert the subject fields via JavaScript in the DOM.
**
function createInput(item) {
// This function takes a item and creates a new input
var newLabel = ' <br><label for="$item-mark">$item:</label>'
var newInput = '<input type="text" id="$item-mark-id" name="$item-mark"><br><br>';
newLabel = newLabel.replaceAll("$item", item)
newInput = newInput.replaceAll("$item", item)
// combine into a single str
newInput = newLabel + newInput
var studInput = document.getElementById("student-id");
// insert element inputs after student
studInput.insertAdjacentHTML('afterend', newInput);
}
function cleanOldInputs(item) {
var oldELement = item + "-mark-id"
oldELement = document.getElementById(oldELement)
if (oldELement) {
// remove old label and input
oldELement.previousSibling.remove()
oldELement.remove()
} else {}
}
function getAPIcall() {
// This is what your API sends
var responsObject = ["writing", "creativity"];
// loop throug
responsObject.forEach(item => {
// if you already picked a student clean old inputs from DOM
cleanOldInputs(item)
// send to function for input creation
createInput(item)
})
}
// get the Student Input
var studentSelect = document.getElementById("student-id");
studentSelect.addEventListener("click", function() {
// Fire anything you like
getAPIcall()
});
<form action="/action_page.php">
<label for="student">Choose a student:</label>
<select name="student" id="student-id">
<option value="harry">harry</option>
<option value="ivy">ivy</option>
</select>
</form>
Quick and dirty**

Symfony & js : button not working in certain conditions

I have a simple "plus/minus" functionality for the product quantity on the product detail page on a shopware6 site (version 6.4.8.1) (See attached image)
See here my code in /views/storefront/page/product-detail/buy-widget-form.html.twig.
{% block page_product_detail_buy_quantity_container %}
<div class="col-12 quantity-container">
<div class="row">
<div class="col-5 col-md-3 label-quantity">
<span>{{ "detail.labelQuantity"|trans|sw_sanitize }}</span>
</div>
<div class="col-7 col-md-9 quantity-input-panel">
{% block page_product_detail_buy_quantity %}
<div class="quantity-inner">
<span class="min button" id="moins" {#onclick="minus()"#}> {% sw_icon 'minus' %} </span>
<input id="amountToBasket" type="text" name="lineItems[{{ page.product.id }}][quantity]" value="{{product.minPurchase}}" autocomplete="off" maxlength="2" class="form-control">
<input id="minPurchase" type="hidden" name="minPurchase" value="{{product.minPurchase}}" autocomplete="off" class="form-control">
<input id="maxRange" type="hidden" name="maxRange" value="{{product.calculatedMaxPurchase}}" autocomplete="off" class="form-control">
<input id="purchaseSteps" type="hidden" name="purchaseSteps" value="{{product.purchaseSteps}}" autocomplete="off" class="form-control">
<span class="plus button" id="plus" {#onclick="plus()"#}> {% sw_icon 'plus' %}</span>
</div>
{% endblock %}
</div>
</div>
</div>
{% endblock %}
And here's my js file related to the plus/minus buttons.
var minPurchase = $("#minPurchase").val();
var maxRange = $("#maxRange").val();
var count = $("#amountToBasket").val();
$("#plus").click(function () {
if (count < maxRange){
count++;
$("#amountToBasket").val(count);
}
});
$("#moins").click(function () {
if (count > minPurchase){
count--;
$("#amountToBasket").val(count);
}
});
PROBLEM : This works perfectly for ALL products where the minimum purchase quantity is equal to 1. BUT if we click on the plus or the minus for every product having the minimum purchase quantity greater than 1, it's doing nothing. It gives the impression that the buttons are deactivated in this case.
Do you have any clue on what is going on?
as replied by #DarkBee, I simply needed to specify the value type of the "count" function.
var count = parseInt($("#amountToBasket").val());

how can i resolve the issue in displaying the ajax search results in django?

Problem
The results are being retrieved by the ajax search function but when I display the data retrieved in the selector using $(selector).htm(data) it loads whole the page with a page with correct search results.
The code is attached below with the screenshot of what I'm getting from this code for a better understanding.
JS
$('#searchsubmit').on('click', function(e){
e.preventDefault();
q = $('#search').val();
console.log(q);
updateContentBySearch(q);
});
function updateContentBySearch(q) {
var data = {};
data['search_by'] = q
// data["csrfmiddlewaretoken"] = $('#searchform [name="csrfmiddlewaretoken"]').val();
$.ajax({
method: 'POST',
url: "{% url 'main:Search' %}",
data: {
'search_by': q,
'csrfmiddlewaretoken' : $("input[name=csrfmiddlewaretoken]").val()
},
success: function (data) {
searchSuccess(data)
}
});
}
function searchSuccess(data, textStatus,jqXHR)
{
$('#search-results').html(data);
}
HTML
<div class="row">
<div class="row justify-content-center" style="text-align:center">
<form class="d-flex col-md-6" id="searchform" method="POST">
{% csrf_token %}
<div class="input-group mb-3" style="text-align:center">
<input name="q" type="text" class="form-control" placeholder="Search" id="search">
<button class="btn btn-primary shadow px-5 py-2" type="submit" id="searchsubmit">Search</button>
</div>
</form>
</div>
<hr style="border-top: 1px solid #ccc; background: transparent;">
<div class="row" id="search-results">
{% regroup transaction by productID as ProductList %}
{% for productID in ProductList %}
///some code
</div>
{% endfor %}
</div>
VIEWS
#csrf_exempt
def search(request):
q = request.POST.get('search_by')
print(q)
product = Products.objects.all()
cart_product_form = CartAddProductForm()
transaction = transactions.objects.filter(productID__name__icontains=q,status='Enable').order_by('productID')
print(transaction)
context={
'products':product,
'transaction': transaction,
'cart_product_form':cart_product_form
}
html = render_to_string('main/home.html',context)
return JsonResponse(html,safe=False , content_type="application/json")
SCREENSHOT
Now in this screenshot u can see it showing me two banners and search bars and after the second the products from the search results are displayed. It's like it loads the whole page again within the page from the selector i have passed data too.
DOES ANYONE KNOWS HOW TO RESOLE THIS ISSUE OR WHERE I HAVE DONE WRONG.
because you render 'main/home.html' agin ! you just need send a json response with your context data and add it to web page with JS or create a new html template and render that with your context data and send that as response!

Dynamically display list of checked checkboxes values js/jquery

I would like to display dynamically a list of the chosen options using javascript or jQuery when the user changes his options.
PS: I'm using Django + Python to generate the options and bootstrap to style them.
Here is my code:
{% for option in options %}
<div class="input-group" style="margin-bottom: 7px;">
<div class="input-group-prepend">
<div class="input-group-text">
<input type="checkbox" name="checks[]" aria-label="Radio button for following text input" class="option_choice" class="ipad_pro" value="{{ option.name }}">
</div>
</div>
<input style="background-color: #fff;" type="text" class="form-control" disabled=True value="{{ option.name }} {{ option.price }}€" aria-label="Text input with radio button">
</div>
{% endfor %}
<ul id='options_display'></ul>
Here's what I've attempted:
var getChecked= function() {
var n = $("input:checked");
var options_display = $("#options_list")
console.log(n)
if (n.length != 0) {
$.each(n, function(index, value) {
options_display.append("<li>" + value.defaultValue + "</li>")
});
}
else {
options_display.html("<h3 class'text-center'>No Options</h3>")
}
};
getChecked()
$( "input[type=checkbox]" ).on( "click", getChecked);
The problem with that is that it doesn't reset the content of the <ul> which means that I get elements twice when I select a new one.
Please help me if you know the answer to my problem.
You can empty options_display on each click like
$("#options_list").empty();
before the condition.

Categories