Django dynamic formset with Jquery Ui autocomplete - javascript

Hi there I am fairly new to django and need to add dynamic formsets with autocomplete functions for every from. I am not entirely sure what I am doing wrong i have tried a few approaches and this is my most recent!
I have function called AutoproductComplete which receives the id of the current formset form input that i want to add the auto complete to. It doesnt work, no errors, not sure why. I also did it after the after method so assume the form has been added to the DOM?'
'html'
<form class="form-horizontal" method="POST" action="">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<div class="row form-row spacer">
<div class="input-group" style="padding:5px;">
{{form.productName}}
{{form.orderQuantity}}
<div class="input-group-append">
<button class="btn btn-success add-form-row"
style="margin:5px;">+</button>
</div>
</div>
</div>
{% endfor %}
<br>
<div class="row spacer">
<div class="col-12 offset-9">
<button type="submit" class="btn btn-block btn-
dark">Create Order</button>
</div>
</div>
</form>
JavaScript
'''
function AutoproductComplete(id){
const products = [];
console.log("This is working")
console.log(id)
{% for instance in products %}
products.push("{{instance.product_name}}")
{% endfor %}
$(id).autocomplete({
classes: {"ui-autocomplete-input": "highlight"},
source: products,
minLength: 1,
});
};
AutoproductComplete("id_form-0-productName" )
function cloneMore(selector, prefix) {
var newElement = $(selector).clone(true);
var id = ""
var total = $('#id_' + prefix + '-TOTAL_FORMS').val();
`enter code here`newElement.find(
':input:not([type=button]):not([type=submit]):not([type=reset])')
.each(function() {
if ($(this).attr('name')){
var name = $(this).attr('name').replace('-' + (total-1) + '-', '-
' + total + '-');
id = 'id_' + name;
$(this).attr({'name': name, 'id':
id}).val('').removeAttr('checked');
}
});
total++;
$('#id_' + prefix + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
var conditionRow = $('.form-row:not(:last)');
conditionRow.find('.btn.add-form-row')
.removeClass('btn-success').addClass('btn-danger')
.removeClass('add-form-row').addClass('remove-form-row')
.html('<span class="glyphicon glyphicon-minus" aria-hidden="true" > -
</span>')
AutoproductComplete(id)
return false;
}
$(document).on('click', '.add-form-row', function(e){
e.preventDefault();
cloneMore('.form-row:last', 'form');
return false;
});
'''

You can use DAL
django-autocomplete-light
As it says, its quite lightweight and IMHO easily and highly configurable.
You can find the docs here:
https://django-autocomplete-light.readthedocs.io/en/master/

Related

Dynamic generated modal and action of a form

I have this error
invalid literal for int() with base 10: '" + key + "'
I generate the
session['Exit'] is a dictionary inside a dictionary
DictItems = {index:{'foo':foo.foo, ...}}
where index is a int
generated like this
numkey = len(session['Exit'])
ind = int(numkey) + 1
index = str(ind)
The code I was trying to create is
<div class="container-fluid">
<div class="row">
<table class='table table-responsive table-sm w-auto small'>
<tbody>
<div class="col-xs-2">
{% for key, items in session['Exit'].items() %}
{% if key %}
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#new_value" data-key="{{key}}" data-price="{{items.price}}" onclick="updateModal(this)">
{{items.price}}
</button>
{% endif %}
{% endfor %}
</div>
</tbody>
</table>
</div>
</div>
<!--Modal -->
<div class="modal fade" id="new_value" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">New_Value</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form id="modal-form" action="" method='POST' >
<div class="modal-body">
<p id="modal-text"></p>
<input class="form-control" name="new_value" step="any" required>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button class="btn btn-primary" type="submit">Change</button>
</form>
</div>
</div>
</div>
</div>
<!---Modal -->
{% if session['Exit'] %}
<script>
function updateModal(element) {
var key = element.dataset.key;
var price = element.dataset.price;
var form = document.getElementById("modal-form");
form.action = "{{url_for('salidas.change_price', key=" + key + ")}}";
document.getElementById("modal-text").innerHTML = "you are going to change the value $" + price + ", are you sure?";
document.getElementsByName("new_value")[0].value = price;
}
</script>
{% endif %}
I imagine that it coud be because the session['Exit'] could be empty, so i tried a {% if session['Exit'] %} but stop working when session has elements and gives the error
still if session session['Exit'] doesnt exist it shouldnt render
in other: i tried to make the key int
data-key="{{key|int}}
also in the script
var key = parseInt(element.dataset.key);
and in the key
+ parseInt(key) +
still in the url_for because is a string shouldnt give me a problem
so i tried to make the url like this in a triple level
form.action = "\"{{url_for('salidas.change_price', key=" + key + ")}}\"";
i still have the same problem
any idea what else could i try?
EDIT: the solution
basically as Detlef said
"doesn't know about the javascript variable key"
the reason escapes my understanding, because this string
document.getElementById("modal-text").innerHTML
works
so what i did is in the button that calls the data-key, renamed it to data-url and generated the url_for
and from there i just called it, leaving something like this
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#new_value" data-url="{{url_for('salidas.change_price', code=key)}}" data-price="{{items.price}}" onclick="updateModal(this)">
{{items.price}}
</button>
and the javascript
<script>
function updateModal(element) {
var url = element.dataset.url;
var price = element.dataset.price;
var form = document.getElementById("modal-form");
form.action = url;
document.getElementById("modal-text").innerHTML = "you are going to change the value $" + price + ", are you sure?";
document.getElementsByName("new_value")[0].value = price;
}

How to style each div that is created by JavaScript code

I'm creating a site for emails, where a user upon clicking a mailbox (inbox, sent, archived) I will show them all the emails that belong to said mailbox.
Now my problem is the layout, the borders of each email are not displaying the way I want. This is how it should be, where the email with gray background is a read one, while white is not:
This is what code turns up:
I want them separated but I can't get it to work. Help would be appreciated!
inbox.js:
function load_mailbox(mailbox) {
// Show the mailbox and hide other views
document.querySelector('#emails-view').style.display = 'block';
document.querySelector('#compose-view').style.display = 'none';
// Show the mailbox name
document.querySelector('#emails-view').innerHTML = `<h3>${mailbox.charAt(0).toUpperCase() + mailbox.slice(1)}</h3>`;
//get me all the emails in inbox(example)
fetch(`/emails/${mailbox}`)
.then(response => response.json())
.then(emails => {
//for each email
emails.forEach(myFunction);
function myFunction(item) {
//create a new div htmlelement
const element = document.createElement('div');
//give it a class in case i need it
element.setAttribute("class", "email-dv")
//add info to this div
element.innerHTML += item.sender + "<br>";
element.innerHTML += item.subject + "<br>";
element.innerHTML += item.timestamp + "<br>";
//create the borders for the div
//issue here, it is not creating a rectangle for each div
element.style.boder = "groove";
//if email is not read
if (item.read === false) {
element.style.backgroundColor = "white";
}
else {
element.style.backgroundColor = "grey";
}
element.addEventListener('click', function() {
console.log('This element has been clicked!')
});
//add it to the main div for all emails
document.querySelector('#emails-view').append(element);
}
});
inbox.html :
{% extends "mail/layout.html" %}
{% load static %}
{% block body %}
<h2>{{ request.user.email }}</h2>
<button class="btn btn-sm btn-outline-primary" id="inbox">Inbox</button>
<button class="btn btn-sm btn-outline-primary" id="compose">Compose</button>
<button class="btn btn-sm btn-outline-primary" id="sent">Sent</button>
<button class="btn btn-sm btn-outline-primary" id="archived">Archived</button>
<a class="btn btn-sm btn-outline-primary" href="{% url 'logout' %}">Log Out</a>
<hr>
<div id="emails-view" >
</div>
<div id="compose-view">
<h3 id="h">New Email</h3>
<form id="compose-form">
<div class="form-group">
From: <input disabled class="form-control" value="{{ request.user.email }}">
</div>
<div class="form-group">
To: <input id="compose-recipients" class="form-control">
</div>
<div class="form-group">
<input class="form-control" id="compose-subject" placeholder="Subject">
</div>
<textarea class="form-control" id="compose-body" placeholder="Body"></textarea>
<input type="submit" class="btn btn-primary" id="submit-button"/>
</form>
</div>
{% endblock %}
{% block script %}
<script src="{% static 'mail/inbox.js' %}"></script>
{% endblock %}
Well, first of all you have a typo:
element.style.boder you're missing the "r" in border. Can you check that first?

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

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.

JQuery:Not able to fetch value of "td" when onclick on button happens second time

Following is the code of my table. In the action column i have a buttons named accept and reject. On click on reject I want to get the values of 2 and 3 "td" present in that "tr".
<table class="w3-table" id="tbl_task" width="100%">
<tr>
{% for ele in d|slice:":1" %} {% for key in ele.keys %}
<th>{{ key }}</th>
{% endfor %} {% endfor %}
<th>Action</th>
</tr>
{% for ele in d %}
<tr class="class_1">
{% for k, v in ele.iteritems %} {% if k in "Assigned_Users" %}
<td>
{% if v|length > 2 %}
<div style="width: 80%;max-height: 37px;overflow:auto;margin-left: 32px;">
{% for ch in v %} {{ ch|linebreaksbr }} {% endfor %}
</div>
{% else %} {% for ch in v %} {{ ch }} {% endfor %} {% endif %}
</td>
{% else %}
<td>
{{ v }}
</td>
{% endif %} {% endfor %}
<td class="noexcel">
<div id="td_button_div">
<button id="status_accepted" class="btn btn-default btn-sm" name="accept">
<span class="glyphicon glyphicon-ok"></span> Approve
</button>
<button id="status_rejected" class="btn btn-default btn-sm" name="reject" data-toggle="modal" data-target="#myModal">
<span class="glyphicon glyphicon-remove"></span> Reject
</button>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">Modal title
</h4>
</div>
<div class="modal-body">
<label>Remarks</label>
<textarea name="textarea" style="color:black;width:100%"></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close
</button>
<button type="button" class="btn btn-primary" id="save_remarks">Save changes
</button>
</div>
</div>
</div>
</div>
</div>
</td>
</tr>
{% endfor %}
At first time I am getting data properly but at second click only modal is displayed with the existing values.
Following is my JQuery code:
$('#status_rejected').on('click', function(e){
var current_row = ' ';
var task_name = ' ';
var current_status = ' ';
var notes = ' ';
alert("inside reject function");
current_row = $(this).closest('tr');
task_name = current_row.find("td:eq(2)").text();
current_status = current_row.find("td:eq(0)").text();
alert("cstatus--->"+$.trim(current_status)+"\n"+"tname"+$.trim(task_name));
var status = "reject"
$("textarea").val(" ");
$("#save_remarks").on('click',function(){
alert("inside save changes on click");
notes = $.trim($("textarea").val());
alert("cstatus"+$.trim(current_status)+"\n"+"tname"+$.trim(task_name));
});
});// end of show model
Need help with this?
I was able resolve this in the following way:
$('.noexcel #status_rejected').on('click', function(e){
var current_row = ' ';
var task_name = ' ';
var current_status = ' ';
var notes = ' ';
var cnt = 0;
current_row = $(this).closest('tr');
task_name = current_row.find("td:eq(2)").text();
current_status = current_row.find("td:eq(0)").text();
var status = "reject"
$("textarea").val(" ");
$("#save_remarks").on('click',function(){
notes = $.trim($("textarea").val());
if(current_status != ' ' && task_name != ' ' && notes != ' ' && current_row != ' '){
ajax_call(current_row, current_status, task_name, notes, status);
current_row = current_status = task_name = notes = ' ';
}
}); // end of onclick of modal save button
});// end of show model
function ajax_call(current_row, current_status, task_name, notes, status){
$.ajax({
type:'post',
url:'/ajax/change_ftrack_status/',
data:{
currentStatus : current_status,
taskName : task_name,
status : status,
notes : notes
},
success:function(data){
$.each(data, function(key, value){
if (key == "ftrack_status"){
current_row.find("td:eq(0)").html(value);
}
else if (key == "updated_on"){
current_row.find("td:eq(1)").html(value);
}
}); // end of for each
// disable the reject button
current_row.find("td #status_rejected").prop("disabled", true);
}
}); //end of ajax
}

pass variables to a bootstrap modal

I have a javascript confirm / cancel pop up box that dynamically unchecks a checkbox and also dynamically hides or shows a menu_entry that is part of a list that appears on the form, only when the user selects the ok button on the js confirm pop up box.
I am now trying to change the js confirm to a bootstrap modal, but I am uncertain how to pass the variables to the bootstrap modal code and get the same functionality of the js confirm pop up box.
Here is my working html code that has the call to the javascript confirm pop up box:
{% for id, menu_entry, selected, item_count in menu_entries %}
<div class="available_resume_details_height">
<input type="checkbox"
style="width:1.5em; height:1.5em;"
name="selected_items"
value="{{ id }}"
{% if selected %}checked="checked"{% endif %}
onclick="checkboxUpdated(this, {{ item_count }}, '{{ menu_entry.label }}', {{ id }});"
/>
<span style="cursor: pointer;"
rel="popover"
data-content="{{ menu_entry.tooltip }}"
data-original-title="{{ menu_entry.label }}"
{{ menu_entry.label }}
</span>
</div>
{% endfor %}
Here is my javascript code to display the confirm pop up and uncheck the checkbox and show/hide the list entry:
function checkboxUpdated(checkbox, count, label, id) {
if (checkbox.checked) {
$('#menu_entry_' + id).show();
} else {
if (count > 0) {
if (! confirm('{% trans "You have '+ count +' saved '+ label +'.\n\nAre you sure you want to delete your ' + count + ' saved ' + label +'?" %}')) {
checkbox.checked = true;
return;
}
}
$('#menu_entry_' + id).hide();
}
}
Here is the new html code that has the call to the bootstrap modal. This does make the bootstrap modal appear:
{% for id, menu_entry, selected, item_count in menu_entries %}
<div class="available_resume_details_height">
<input type="checkbox"
style="width:1.5em; height:1.5em;"
name="selected_items"
value="{{ id }}"
{% if selected %}checked="checked"{% endif %}
{% if selected %}
data-confirm="{% blocktrans with entry_label=menu_entry.label %}Are you sure you want to remove your {{ item_count }} selected {{entry_label}} Resume Details?{% endblocktrans %}"
{% endif %}
/>
<span style="cursor: pointer;"
rel="popover"
data-content="{{ menu_entry.tooltip }}"
data-original-title="{{ menu_entry.label }}"
{{ menu_entry.label }}
</span>
</div>
{% endfor %}
Here is my bootstrap modal code that is not working. I am unsure how to pass the variables and get the same functionality of the js confirm pop up:
$(document).ready(function() {
$('input[data-confirm]').click(function(ev) {
var href = $(this).attr('href');
if (!$('#dataConfirmModal').length) {
$('body').append('<div id="dataConfirmModal" class="modal modal-confirm-max-width" role="dialog" aria-labelledby="dataConfirmLabel" aria-hidden="true"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true"><icon class="icon-remove"></icon></button><h4 class="modal-title" id="dataConfirmLabel">{% trans "Confirm" %} - {{ resume_detail_temp_value }}</h4></div><div class="modal-body"></div><div class="modal-footer"><button class="btn" data-dismiss="modal" aria-hidden="true">{% trans "Cancel" %}</button> <a class="btn-u btn-u-blue" id="dataConfirmOK">{% trans "Confirm" %}</a></div></div>');
}
$('#dataConfirmModal').find('.modal-body').html($(this).attr('data-confirm'));
$('#dataConfirmModal').modal({show:true});
$('#dataConfirmOK').click(function() {
// handle checkbox function here.
});
return false;
});
});
The bootstrap modal should show/hide the list entry and only uncheck the checkbox when the confirm button is selected.
EDIT: ADDED CHECKBOX CODE:
<input type="checkbox"
style="width:1.5em; height:1.5em;"
name="selected_items"
value="{{ id }}"
{% if selected %}checked="checked"{% endif %}
onclick="checkboxUpdated(this, {{ item_count }}, '{{ menu_entry.label }}', {{ id }});"/>
Data attributes may help you pass the data you need in the function in a seamless manner and also help you avoid maintenance unfriendly inline JavaScript. Set up three event listeners as follows:
function checkboxUpdated(checkbox, count, label, id) {
var checkbox = this,
count = $(checkbox).data('count'),
label = $(checkbox).data('label'),
id = checkbox.value;
if(checkbox.checked) {
$('#menu_entry_' + id).show();
} else {
if (count > 0) {
$('#confirm_modal').data('element', checkbox).find('div.modal-body p:first')
.html( 'You have ' + count + ' saved ' + label + '. Are you sure you want to delete your ' + count + ' saved ' + label + '?' ).end()
.modal('show');
return;
}
$('#menu_entry_' + id).hide();
}
}
$(function() {
$(':checkbox').on('change', checkboxUpdated).change();
$('.confirm-no').on('click', function() {
var element = $('#confirm_modal').data('element');
element.checked = true;
});
$('.confirm-yes').on('click', function() {
var element = $('#confirm_modal').data('element'),
id = element.value;
$('#menu_entry_' + id).hide();
});
});
DEMO
UPDATE
http://jsfiddle.net/n0ypwceo/3/
**HTML**
<div class="available_resume_details_height">
<input type="checkbox" data-confirm='Are you sure you want to remove? [1] ' value="id1" /> <span style="cursor: pointer;">Checkbox</span>
<br/>
<input type="checkbox" data-confirm='Are you sure you want to remove? [2]' value="id2" /> <span style="cursor: pointer;">Checkbox</span>
</div>
<div id="dataConfirmModal" class="modal modal-confirm-max-width" role="dialog" aria-labelledby="dataConfirmLabel" aria-hidden="true"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true"><icon class="icon-remove"></icon></button><h4 class="modal-title" id="dataConfirmLabel">Confirm?</h4></div><div class="modal-body"></div><div class="modal-footer"><button class="btn" data-dismiss="modal" aria-hidden="true">"Cancel"</button> <a class="btn-u btn-u-blue" id="dataConfirmOK">"Confirm"</a></div></div>
<div id="menu_entry_id1" style="display:none">menu entry id 1</div>
<div id="menu_entry_id2" style="display:none">menu entry id 2</div>
JQ:
// global vars
//checkbox that is clicked
var $checkboxClicked;
//If the confirm button is clicked
var confirm=false;
$(document).ready(function () {
$('input[data-confirm]').click(function (ev) {
//box that is clicked placed in a variable
$checkboxClicked = $(this);
//get and store confirm text
var dataConfirmTxt=$checkboxClicked.attr('data-confirm')
confirm = false;
//var href = $(this).attr('href');
//append confirm text
$('#dataConfirmModal').find('.modal-body').html(dataConfirmTxt);
//show moadl
$('#dataConfirmModal').modal('show')
//if confirm button selected
$('#dataConfirmOK').click(function () {
// the confirm button is clicked
confirm=true;
// hide modal
$('#dataConfirmModal').modal('hide')
});
return false;
});
//modal event: before hide
$('#dataConfirmModal').on('hidden.bs.modal', function (e) {
//get menu id
var id=$checkboxClicked.val();
//alert(id+'/'+confirm);
if(confirm==true)
{
// check checkbox
$checkboxClicked.prop('checked', true);
// show menu entry
$('#menu_entry_' + id).show();
}
else
{
// uncheck checkbox
$checkboxClicked.prop('checked', false);
// hide menu entry
$('#menu_entry_' + id).hide();
}
})
});
I hope this could help you. You could see my code from here http://jsfiddle.net/p0mpv9e0/3/.
Why your code is not working is because you forget to put attribute 'data-confirm' to input element. It should be:
<input type="checkbox" data-confirm ... />
I'm not sure what do you mean by pas variables but if you want to get data that stored in input element you could get it using variable "this" inside the event callback.
$('input[data-confirm]').click(function() {
var self = this; // it's object that store data from input element
});

Categories