Bootstrap-Select not updating on mobile - django

I am using Bootstrap-select for multi-select items with Django. It works fine on desktop, but when the native mobile drop-down is enabled, the selected values of the dropdown do not populate.
HTML
<!-- start product brand info -->
<div class="row">
<div class="col-md-6 col-xs-*">
<div>
<label for="id_brand-name" class="form-label">Products</label>
</div>
<select multiple class="form-control selectpicker mb-3" id="id_brand-name" name="brand-name" mobile="true" multiple required>
{% for product in products %}
<option value="{{product.id}}" id="optiion">{{ product.brand.name | title }} - {{product.name | title}}</option>
{%endfor%}
</select>
<div class="invalid-feedback">
Select at least one product.
</div>
</div>
</div>
<!-- end product info -->
<script>
//Enble native drop down on mobile
window.onload = function () {
$('#id_brand-name').selectpicker({
container: 'body'
});
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) {
$('#id_brand-name').selectpicker('mobile')
}};
</script>
No matter how many items are selected, the selector always shows Nothing selected. When the data is posted, it is apart of the form though.

I like to use bootstrap-select, but this problem has been bothering me for a long time
Similar questions can be found on github, but no perfect answer.
The reason is that it will always refresh his title, no matter how remove() is done externally, and you can't change it's style on iphone Safari and Firefox.
So my solution is: if you can't remove it, then join it.
You have to change the original file: bootstrap-select.js
Search for: bs-title-option, next line you will find:
this.selectpicker.view.titleOption.value = '';
And add two lines down:
this.selectpicker.view.titleOption.value = '';
// new add
this.selectpicker.view.titleOption.disabled='true';
this.selectpicker.view.titleOption.textContent=this.options.title;
//
Done
When you use $('#id_brand-name').selectpicker('mobile')
The title text show on first empty option, and it can't be choose.
try it!

Related

HTMX not triggering correct query on pickadate.js selection

I use django-forms-dynamic package and htmx to dynamically load available options on a MultipleChoiceField. The options are based on a date field, for which I use pickadate.js by Amsul.
The initial query gets the correct choices from the database. However, if the date is changed, the query is lagging one step behind. So, let's asume 1.11.2022 is initially selected. If changed to 4.11.2022, the query is made for the 1.11.2022. If 28.11.2022 is selected, 1.11.2022 is queried, etc.
reservation_form.html
<div class="col-lg-6">
<div class="form-floating">
{% render_field reservation_form.date class="datepicker form-control mb-3"
hx-get="/reservation/filter-seats"
hx-include="#id_dinner"
hx-trigger="click change"
hx-target="#id_seat_reservation"
%}
<label for="id_date">Dinner Date</label>
</div>
<div class="form-floating">
{% render_field reservation_form.amount_guests class+="form-control" placeholder="" %}
<label for="id_amount_guests">Guests</label>
</div>
<div class="visually-hidden">
{% render_field reservation_form.dinner %}
</div>
<div class="form-check">
{% render_field reservation_form.seat_reservation class+="form-select" %}
<label for="id_seat_reservation">Select Seats</label>
</div>
</div>
pickadate script
<script>
var $input = $('.datepicker').pickadate({
format: 'yyyy-mm-dd',
formatSubmit: 'yyyy-mm-dd',
min: 0,
max: 90,
disable: {{ blocked_dates }},
firstDay: 1,
})
var picker = $input.pickadate('picker')
</script>
What am I missing?
You have set the triggers as hx-trigger="click change". First, this is incorrect, you have to separate events with a comma, right now HTMX tries to evaluate change as a trigger modifier without success. Therefore you only have the click trigger event, HTMX submits the form when you click on the input element. At the same time pickadate.js also listens to the click event and opens the datepicker widget. After selecting a date the form dispatches the change event, but you have disabled that for HTMX so it will not submit the form again. Next time you click on the input element HTMX submits the form with the previously selected value.
To fix the issue just remove the hx-trigger attribute. For input fields the default trigger is already the change event, therefore HTMX will submit the form when pickadate.js enters the selected date into the input field.

Using different content object passed from Views to Template depending on what button user presses

I currently have one model called Comments.
After entering in a youtube Channel in a form, the user is taken to the index template that shows all the comments on that youtube channels videos that includes one of three key words (Keyword A, Keyword B , Keyword C).
I would like to add a feature so there are three links/buttons on the top of the page (each for one of the keywords).
The user can press that link and without page reload (does this mean I will need AJAX?) see the comments with that keyword, instead of all comments with any of the three keywords.
I am currently sending four content variable objects from views to the template (one with all the comments and three other objects each that just contain the comment objects for that keyword).
So the template has access to the data I need, I just need to make it so that when one of the links/buttons are clicked, it only shows that content.
Views
def addTodo(request):
new_item =Channel(channel=request.POST['channel'])
#if channel exists render page with comments
if Channel.objects.filter(channel=new_item.channel).exists():
channel_obj=Channel.objects.get(channel=request.POST['channel'])
comments_object=Comments.objects.filter(channel=channel_obj)
comments_objectA=Comments.objects.filter(channel=channel_obj, key="keywordA")
comments_objectB=Comments.objects.filter(channel=channel_obj, key="keywordB")
comments_objectC=Comments.objects.filter(channel=channel_obj, key="keywordC")
return render(request, 'todo/index.html', {'comments_all': comments_object, 'commentsa': comments_objectA,'commentsb': comments_objectB,'commentsc': comments_objectC})
Index Template
#three buttons/links on top to allow user to sort..the part Im not sure how to do:
<button type="button"onclick="justshowrelatedcomment>KeywordA!</button>
<button type="button"onclick="justshowrelatedcomment>KeywordB</button>
<button type="button" onclick="justshowrelatedcomment>KeywordC</button>
#the comment structure, would want to replace comments_all with whatever button is clicked on.
<div class="new_comment">
<!-- build comment -->
{%for a in comments_all%}
<ul class="user_comment">
<!-- current #{user} avatar -->
<!-- the comment body --><div class="comment_body">
<p>{{ a.question }}</p>
</div>
</ul>
{% endfor %}
</div>
</div>
I'm quite stuck.. Is this possible without Ajax?
If Ajax is my only/best option, how should I go about that?
I was using this solution to avoid ajax, as I couldn't figure out how to use ajax.
Thanks and cheers.
You can do it without ajax, but it does not reduce the size of loaded page. The non-ajax client-side solution is to assign each comment element a class or attribute based on its keyword - here you have used a <ul> element with user_comment class already.
So try to put the keyword as an attribute or class to your comment divs. Then you can select and then hide or show each keyword class of comments using javascript coding.
It can be done in different ways but it would be easy using pure js so I am putting the template for the implementation:
<!-- toggling comments -->
<script>
function toggle_keyword(keyword) {
document.querySelectorAll('.user_comment').forEach(function (e) {
e.style.display = 'none';
});
document.querySelectorAll('.' + keyword).forEach(function (e) {
e.style.display = 'block';
});
}
</script>
<button type="button" onclick="toggle_keyword('KeywordA');">hide/show KeywordA!</button>
<button type="button" onclick="toggle_keyword('KeywordB');">hide/show KeywordB</button>
<button type="button" onclick="toggle_keyword('KeywordC');">hide/show KeywordC</button>
#the comment structure, would want to replace comments_all with whatever button is clicked on.
<div class="new_comment">
<!-- build comment -->
{%for a in comments_all%}
<ul class="user_comment {{ a.key }}">
<!-- current #{user} avatar -->
<!-- the comment body -->
<!-- here I added a.key as a class to the div -->
<div class="comment_body">
<p>{{ a.question }}</p>
</div>
</ul>
{% endfor %}
</div>
</div>
Definitely Ajax will be best option for you. You just need to post one flag while clicking button with using ajax. On that flag basis you can decide which data you want to pass for your html
HTML
<button onclick="justshowrelatedcomment('A')">KeywordA</button>
<button onclick="justshowrelatedcomment('B')">KeywordB</button>
<button onclick="justshowrelatedcomment('C')">KeywordC</button>
<script>
function justshowrelatedcomment (flag) {
$.ajax({
url: 'addTodo',
type: 'POST',
data: {
flag: flag
},
success: function(data){
return data;
}
});
}
</script>
View
def addTodo(request):
flag = request.POST['flag']
new_item =Channel(channel=request.POST['channel'])
Hopefully this will work for you.

How to call a django url after clicking on a bootstrap tab and show results on the tab content?

I have created two bootstrap tabs whose data is comming from django functions. I can easily post essential data of all tabs while the tabs are loaded but I want to load data of each tab once the tab is clicked instead of loading all data together.
Bootstrap uses href or data-target to load a tab content. So, when I set django url in href attribute and activate the tab by JavaScript, the django function is invoked but bootstrap does not open the tab. It always opens the first tab.
<ul id="myTab" class="nav nav-tabs bar_tabs" role="tablist">
<li role="presentation" class="active">Profile
</li>
<li role="presentation" class="">Monitor
</li>
</ul>
<div id="myTabContent" class="tab-content">
<div role="tabpanel" class="tab-pane fade active in" id="tab_content1" aria-labelledby="home-tab">
</div>
<div role="tabpanel" class="tab-pane fade" id="tab_content3" name="tab_content3" aria-labelledby="profile-tab">
{% include "setting/monitor.html" %}
</div>
</div>
My JavaScript code is:
<script>
$(document).ready(function(){
switch("{{section}}"){
case 'monitor':
$('#myTabContent #tab_content3').tab('show');
break;
case 'profile':
$('#myTab a[href="#tab_content1"]').click();
break;
}
})
</script>
I have also used the below javascript to activate second tab, but it does not wok.
$("#myTab").tabs("select", 2);
I appreciate your help.
Bootstrap will show the tab which you marked as "active". So when returning the HTML for 2nd tab make that tab as active by adding class="active" attribute to it.
May be you need to pass that information from view in the context and add that class to appropriate tab in the template.

Displaying a text field along with radio through Django form

Lets say I have a model with 2 fields. With one field being a choice field of radio button Choice1, Choice2 and Other, the next being Other which is a textfield I want the "other" textbox to appar / enabled only when "Other" is selected in the radio button.
This question is not from the django-forms category. This applies more to the front-end category. Everything that is sent from the django server is static. Sure, you can write a form class and override the template for it. Also, you can connect the js script directly to the form class. It is convenient, but not canonical. Just, write the JS script or using JQuery, which will activate the field when you select a particular option.
I wrote for you a small example of how this can be do it.
I hope this helps you.
$('input[type=radio][name=choices]').change(function() {
$('input[type=text][name=other]').prop(
'disabled',
function(i, v) {
return !v;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<p><input name="choices" type="radio" value="choice1">Choice 1</p>
<p><input name="choices" type="radio" value="choice2">Choice 2</p>
<p><input name="other" type="text" disabled></p>
</form>

Can Foundation 4 have a scope?

Can Foundation 4 be initialized only in certain areas of the page?
For instance, if I have 2 divs, can I call foundation("#div2") and all CSS and javascript events are applied only within div#2?
Thanks a 1000!
Generally it won't affect you. The grid system for example is mainly controlled by CSS. For forms, unless you apply the custom class to your form the js for forms elements won't kick in. To illustrate that, one of the two forms below has the custom class and the other don't. Notice that Foundation will add two anchor tags and an unordered list for the form with custom class:
<form id="form1">
<select>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
</form>
<form id="form2" class="custom">
<select>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
</form>
Here's the fiddle to that to see it in action.
UPDATE: For general "section formatting" yes you can apply foundation to some sections of your page. But take note though that the grid system will still be applied even if the grid is outside the section you targeted. Again, that is because they are mainly controlled by CSS. Here's another illustration:
<h1>The Grid System will still be applied to this</h1>
<div class="row1">
<div class="large-5 large-centered columns">
<p class="panel">Centered Div</p>
</div>
</div>
<div id="foundationArea">
<h1>Only apply Foundation here</h1>
<form id="form1" class="custom">
<select>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
</form>
<div class="row">
<div class="large-6 columns panel">
<p>Test</p>
</div>
</div>
</div>
<h1>Foundation is not allowed here</h1>
<form id="form2" class="custom">
<select>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
</form>
See this updated fiddle to show the updated example given here.