javascript/jquery dropdown menu selection not passing GET request - javascript

In my page I have a dropdown menu, and upon selection I want to pass a GET request. This GET request should (ideally) trigger a function from my views.py file and return some data (based on the selection) from my database. However, it doesn't seem like anything actually happens upon dropdown menu selection.
Here is my script that I wrote to trigger the GET request when a selection was made:
<!-- AJAX Call for dropdown menu selection -->
<script type="text/javascript">
var url = $('.dropdown-menu').attr('action');
$('.dropdown-menu-option').click(function(e){
e.preventDefault();
$.ajax({
type: "GET",
url: url,
data: {
class: $('.dropdown-menu-option').val()
},
success: function(result) {
alert ('pass');
},
error: function(result) {
alert('fail');
}
});
});
</script>
Here is the code for my dropdown menu in my template:
<!-- Query based content for dropdown menu -->
<select class="dropdown-content">
{% if current_user_properties %}
{% for property in current_user_properties %}
<option class="dropdown-menu-option" value="{{property.id}}">{{property.name}}</option>
{% endfor %}
{% else %}
<option>You don't have any properties</option>
{% endif %}
</select>
Lastly, here is the code for the function I wanna run in my views.py
def property_selected(request):
if request.method == 'GET':
selection = request.GET.get('class', None)
if selection:
selected_data = MeterData.objects.filter(property=selection).order_by(date)
return selected_data
If anyone can help identify what I'm missing/doing wrong, that'd be greatly appreciated. Thanks!!

$('.dropdown-menu-option') returns a collection of html nodes, since there are many elements that match this selector.
So when you pass $('.dropdown-menu-option').val() to the class property of the data object of ajax options, you are not really passing the value of the selected option.
You can attach a onChange event on the select.dropdown-content and get the value of the selected option like this:
$('.dropdown-content').on('change', function(e){
var selectedOption = $(this).find(':selected').val()
$.ajax({
type: "GET",
url: url,
data: {
class: selectedOption
},
...
})

Related

Select2 shows TEXT but submits IDs, using with Flask, WTForms

I'am trying to implement the Select2 drop-down (data via ajax) feature while using WTForms. Almost everything is working, meaning data is being fetched properly and processed in the expected 'ID and TEXT' format that Select2 expects.
However I am getting a "Not a valid choice" error upon submitting - when validate_on_submit is run. This appears to be caused by the fact that Select2 is submitting the ID number and not the TEXT. This is weird because it is displaying the text on the page itself when searching and actually making the selection.validate_on_submit is expecting 0 or 1 and not a random integer which is why it throws and error. How do I workaround this? How do I get the actual TEXT submitted?
And also any text/selection in previous Select2 fields disappears when adding a line or deleting one (I guess when running render_template??). Choices that are specified in flask/python are left intact as they should.
The most similar questions I could find are question1 and question2 but either there is no answer or I am unable to fully understand and apply it.
Here is some of the code:
Javascript
$(element).parents('.row').find('.item-model').select2({
placeholder: 'Select an option',
ajax: {
url: '/api/1/modelsnew',
dataType: 'json',
method: 'GET',
data: function (params) {
var specificquery = {
name: params.term
}
return specificquery;
},
processResults: function (data) {
var res = data.models.map(function (item) {
return {id: item.hardware_id, text: item.name};
});
return {
results: res
};
},
cache: true
},
minimumInputLength: 2
});
HTML
<div class="col-3">
{{ line.item_model.label}}
{% if line.item_model.data == 'Software' %}
{{ line.item_model(class='form-control item-model', disabled=true) }}
{% else %}
{{ line.item_model(class='form-control item-model') }}
{% endif %}
{% for error in line.item_model.errors %}
<p class="form-control-status text-danger">
{{ error }}
</p>
{% endfor %}
</div>
Flask-WTForm
class DeviceForm(FlaskForm):
item_model = SelectField('MODEL', choices=[('0', 'Select Item')], validators=[DataRequired()])
Further looking into this it appears the same issues are described here question3 and question4 but I am still unable to figure it out. Any help is appreciated!
I can also provide a gif and/or screenshots.
UPDATE:
I found out how to 'get' the TEXT value and display it via console.log but how do I make this the selection for the WTForms SelectField ? Why would it register the ID on submit?
var hereitgoes = $(element).parents('.row').find('.item-model')
$(hereitgoes).on("select2:select", function (e) {
var selectedtext = $(e.currentTarget).text();
console.log(selectedtext)
});

How to "load" dependent drop down upon page load?

I have a form with a dependent drop-down. This secondary drop-down is hidden whenever the primary option selected does not have any secondary options, and when the page first loads. Whenever the form is submitted, only the first field gets cleared out, since most of the time the drop-downs remain the same, however, since the script works whenever there is a change in the primary drop-down, since the load upon does not constitute a change, it just keeps the selected/submitted option on the primary drop-down, and will just display an empty secondary drop-down, even when the primary option selected does have secondary options. I got most of the JS from the drop-down from a tutorial, as I am not very familiar with it. For a more visual understanding:
This is the form when the page first loads
When you select an option that has secondary options, the other dropdown appears
After you select a Station and submit, the Employee # clears, but the other two are supposed to remain, however, when the page reloads upon submission, it looks like this, and the station has been cleared according to the debugger since there are none technically. I don't care so much about the station clearing, but more about not having an empty drop-down that should not be empty.
And when I look at the data that remained in the form, only the work area stayed, because the dependent dropdown does not load until you select another option from the drop down, and if you wanted to be able to see the Box Assembly options again, you'd have to click another option and then go back to Box Assembly (for example)
How could I fix this issue? Is there a way to force the javascript to attempt to load first so that it checks if the option that remained does have the secondary options, whether it has been triggered or not?
forms.py
class WarehouseForm(AppsModelForm):
class Meta:
model = EmployeeWorkAreaLog
widgets = {
'employee_number': ForeignKeyRawIdWidget(EmployeeWorkAreaLog._meta.get_field('employee_number').remote_field, site, attrs={'id':'employee_number_field'}),
}
fields = ('employee_number', 'work_area', 'station_number')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['station_number'].queryset = Station.objects.none()
if 'work_area' in self.data:
try:
work_area_id = int(self.data.get('work_area'))
self.fields['station_number'].queryset = Station.objects.filter(work_area_id=work_area_id).order_by('name')
except (ValueError, TypeError):
pass
elif self.instance.pk:
self.fields['station_number'].queryset = self.instance.work_area.stations.order_by('name')
views.py
def enter_exit_area(request):
enter_without_exit = None
exit_without_enter = None
if request.method == 'POST':
form = WarehouseForm(request.POST)
if form.is_valid():
emp_num = form.cleaned_data['employee_number']
area = form.cleaned_data['work_area']
station = form.cleaned_data['station_number']
# Submission logic
form = WarehouseForm(initial={'employee_number': '', 'work_area': area, 'station_number': station})
else:
form = WarehouseForm()
return render(request, "operations/enter_exit_area.html", {
'form': form,
'enter_without_exit': enter_without_exit,
'exit_without_enter': exit_without_enter,
})
urls.py
urlpatterns = [
url(r'enter-exit-area/$', views.enter_exit_area, name='enter_exit_area'),
path('ajax/load-stations/', views.load_stations, name='ajax_load_stations'),
]
At the end of this html is the script that handles the dependent drop-down
enter_exit_area.html
{% extends "operations/base.html" %}
{% block main %}
<form id="warehouseForm" action="" method="POST" data-stations-url="{% url 'operations:ajax_load_stations' %}" novalidate >
{% csrf_token %}
<div>
<div>
<label>Employee #</label>
{{ form.employee_number }}
</div>
<div>
<label>Work Area</label>
{{ form.work_area }}
</div>
<div class="col-xs-8" id="my-hidden-div">
<label>Station</label>
{{ form.station_number }}
</div>
</div>
</form>
<script>
function loadStations() {
var url = $("#warehouseForm").attr("data-stations-url");
var workAreaId = $(this).val();
var $stationNumberField = $("#{{ form.station_number.id_for_label }}");
$.ajax({
url: url,
data: {
'work_area': workAreaId
},
success: function (data) {
$("#my-hidden-div").show(); // show it
$stationNumberField.html(data);
// Check the length of the options child elements of the select
if ($stationNumberField.find("option").length === 1) {
$stationNumberField.parent().hide(); // Hide parent of the select node
} else {
// If any option, ensure the select is shown
$stationNumberField.parent().show();
}
}
});
}
$("#id_work_area").change(loadStations);
$(document).ready(loadStations);
</script>
{% endblock main %}
station_number_dropdown_options.html
<option value="">---------</option>
{% for station in stations %}
<option value="{{ station.pk }}">{{ station.name }}</option>
{% endfor %}
I see that you have $(document).ready(loadStations);.
But the problem is that in loadStations, you do var workAreaId = $(this).val();.
this will be document, and $(document).val() is an empty string.
Either hardcode the selector in loadStations:
// var workAreaId = $(this).val();
var workAreaId = $("#id_work_area").val();
Or trigger the change from the element instead:
$("#id_work_area").change(loadStations);
// $(document).ready(loadStations);
$("#id_work_area").change();

Send items from forloop populated data in django template through ajax to django view

I have been trying to create a click and populate div with ajax in my django e-commerce application. The project works in such a way that when a customer clicks on a category in men's page it populates another div
gender.html
{%for cate in cat%}
<a href="javascript:getcat()" id="catgend" cats-data="{{cate.catname}}" gen-data="{{gens.gender}}" data-sort-url="{% url 'Home:sortcat' cpk=cate.pk %}" >{{cate.catname}}</a>
{% endfor %}
<div id="products">
<div class="progress">
<img src="{% static 'img/load.gif'%}">
</div>
</div>
This sends the data to my django view through the ajax function called getcat but the data sent through is that of the first item in the loop in-respective of the loop item clicked on. below is my ajax function:
getcat()
function getcat() {
$(".progress").show()
var cat = $("#catgend").attr("cats-data");
var gender = $("#catgend").attr("gen-data");
var url = $("#catgend").attr("data-sort-url");
$.ajax({
url: url,
data: {
'cat': cat,
'gender': gender,
},
success: function (data) {
$("#products").html(data);
}
});
$(".progress").hide()
}
enter code here
From my research i discovered its because they have same ID. How do i solve the issue of dynamically changing the id over the same loop. Thanks
Replace the id attribute with a class attribute since you shouldn't have more than a single element with the same id. Also, we can change cats-data and gen-data to valid data-* attributes.
{% for cate in cat %}
<a href="#" class="catgend" data-cats="{{cate.catname}}" data-gen="{{gens.gender}}" data-sort-url="{% url 'Home:sortcat' cpk=cate.pk %}" >{{cate.catname}}</a>
{% endfor %}
Bind a click event to anchors using the new class name.
$('.catgend').on('click', function (e) {
$('.progress').show()
var data = $(this).data()
$.ajax({
url: data.sortUrl,
data: {
'cat': data.cats,
'gender': data.gen,
},
success: function (data) {
$('#products').html(data);
}
});
$('.progress').hide()
});
Utilise the data attributes to accumulate data values in a simple way.

calling function with ajax, part working but part not working

Sorry if the title isn't very clear. I have search engine that works with ajax function. Right now if I type t in a search box, the tags that contain the word t shows up(ex if I type t, then test shows up) but thing is after I delete the word t all the tags show up in the result part. Does this make sense? if I'm not clear I'll post the picture. I'm not sure why or how to fix this.
Here;s my code.
<h3>Search</h3>
{% csrf_token %}
<input type="text" id="search" name="search" onkeyup="handle_keyup()"/>
<ul id="search-results">
</ul>
Here I can't delete search-results as this will show the search results but on this section when nothing is typed still all the tags show up. (it only shows all when I finish using search bar)
my ajax
function handle_keyup() {
$.ajax({
type: "POST",
url: "/search/",
data: {
'search_text' : $('#search').val(),
'csrfmiddlewaretoken' : $("input[name=csrfmiddlewaretoken]").val()
},
success: searchSuccess,
dataType: 'html'
});
};
function searchSuccess(data, textStatus, jqXHR)
{
$('#search-results').html(data);
}
problem is probably occurring from up there, but I'll post the back end as well. This is python django framework.
def search_titles(request):
# categories = SearchQuerySet().autocomplete(content_auto=request.POST.get('search_text', ''))
categories = Category.objects.filter(name__icontains=request.POST.get('search_text', ''))
return render_to_response('main/ajax_search.html', {'categories' : categories})
ajax_Search.html
{% if categories.count > 0 %}
{% for category in categories %}
<li>{{ category.name }}</li>
{% endfor %}
{% else %}
<li>None to show!</li>
{% endif %}
thanks in advance
This is happening because when the user "deletes" the word, your handle_keyup function is fired, sending a search request of '' to the server.
The server then looks for the empty string '' in the category names and finds it in all of them.
One approach is for the server to check if the search text is empty, and if it is, return nothing. Something like:
def search_titles(request):
txt = request.POST.get('search_text', '')
if txt:
categories = Category.objects.filter(name__icontains=txt)
else:
categories = []
return render_to_response('main/ajax_search.html', {'categories' : categories})

HTML refreshing on click

I'm using the sample found here http://stackoverflow.com/questions/27218680/how-can-i-reload-just-one-div-on-click and I think I'm missing something in my example or maybe the value is not passing as I'm using MPTT instead of a standard menu.
This is how I'm loading my menu found in my base.html -
{% recursetree nodes %}
{{ node.name }}
{% endrecursetree %}
Here is the javascript I've included -
<script>
$(document).on('click','.node',function(e) {
id = $(this).attr("id");
$.ajax({
type: "GET",
url: '/gui/details/' + id,
success: function (result) {
$('.details').html(result);
},
});
});
</script>
I'm then trying to use this id to reload the template here -
<div class="details">
{% include 'gui/details.html' %}
</div>
Here is the view for generating the details -
def display_details(request, list_id):
qs_details = Details.objects.filter(owner=request.user, list=list_id)
return render(request, 'gui/details.html', {'qs_details': qs_details,})
Currently when I click anything on my list it doesn't do anything.

Categories

Resources