Django Select2Widget not getting styled properly with crispy forms - django

I'm using the django-select2 package to implement Searchable Select on a ForeignKey field.
I was successful in getting the functionality to work by following the steps mentioned in the docs but I am having trouble with the styling.
To render my form I use crispy-forms. All the other widgets get rendered properly except the Select2Widget.
As can be seen in the above image, the height and width of the form element is not dynamic like other elements.
HTML code generated:
<div class=""> <select name="current_user" data-minimum-input-length="0" data-allow-clear="true" data-placeholder=""
class="select2widget form-control django-select2" required id="id_current_user">
<option value=""></option>
<option value="">---------</option>
<option value="4" selected>Arpita</option>
</select> </div>
</div>
<div id="div_id_device_admin" class="form-group"> <label for="id_device_admin" class=" requiredField">
Device admin<span class="asteriskField">*</span> </label>
<div class=""> <select name="device_admin" data-minimum-input-length="0" data-allow-clear="true" data-placeholder=""
class="select2widget form-control django-select2" required id="id_device_admin">
<option value=""></option>
<option value="">---------</option>
<option value="4" selected>Arpita</option>
</select> </div>
</div>
This is how I set the widget in ModelForm.
def __init__(self, *args, in_org, **kwargs):
...
self.fields['current_user'].widget = Select2Widget()
self.fields['current_user'].queryset = in_org.user_set.all()
I feel this is mostly an issue with CSS styling and I am unable to figure out the issue. Any help would be greatly appreciated.

For those who are looking for a solution (though I think it's not the best),
you can fix the layout issue by passing attrs={'data-width': '100%'}
e.g.
self.fields['current_user'].widget = Select2Widget(attrs={'data-width': '100%'})
or
current_user = forms.ChoiceField(
widget=ModelSelect2Widget(
model=User,
search_fields=['username__istartswith'],
attrs={'data-width': '100%'},
),
)

Related

Django: Multiselect Unexpected behaviour

Here is my Multiselect
<div class="form-group">
<label>Multiple select using select 2</label>
<select class="js-example-basic-multiple w-100" id='mls' name="resources" multiple="multiple">
<option value="AL">Alabama</option>
<option value="WY">Wyoming</option>
<option value="AM">America</option>
<option value="CA">Canada</option>
<option value="RU">Russia</option>
</select>
</div>
Whenever I try to post despite selecting multiple values I still get only one .
Here is stacktrace.
Variable Value
csrfmiddlewaretoken
'aI5tuSxOtxzGOpMDKR4RcH685yWUFpqkgTeBrYVbQ8kN9ODxnPOytllMTAb11Bib'
acc_id
'1'
resources
'AM'
I tried with getlist as well still getting single value we all can see single values are passing in request itself.
Not sure what might I am doing wrong here .
It seems you are send single value from front.
i tested it:
<form method="GET">
<div class="form-group">
<label>Multiple select using select 2</label>
<select class="js-example-basic-multiple w-100" id='mls' name="resources" multiple="multiple">
<option value="AL">Alabama</option>
<option value="WY">Wyoming</option>
<option value="AM">America</option>
<option value="CA">Canada</option>
<option value="RU">Russia</option>
</select>
</div>
<button type="submit">Show me markers</button>
</form>
i see in request:
"GET /test/testmarkers/?resources=WY&resources=AM HTTP/1.1" 200 1867
And i am sure, you are use not Form.send(). How are you send it?

How to get the value from the drop down box django? without submit button

How to get the value from the dropDown Box in Django Without Submit Button
<div class="single-shorter">
<form action="." method="GET">
<label>Sort By :</label>
<select name="val" id="val">
<option selected="selected" value="name">Name</option>
<option value="price">Price</option>
</select>
</form>
</div>
You can simple obtain it using Ajax but as mentioned in comments in dont want to use that u can use value attribute in option value and using event listner and window.loction.href we can obtain this... This is one example
<select id="foo">
<option value="">Your Dropdown</option>
<option value="http://www.google.com">x</option>
<option value="http://www.facebook.com">y</option>
</select>
<script>
document.getElementById("foo").onchange = function() {
if (this.selectedIndex!==0) {
window.location.href = this.value;
}
};
</script>
as u are using django use this and also dont want to change the value attribute
<select id="my_selection">
<option value="x" href="/link/to/somewhere">value 1</option>
<option value="y" href="/link/to/somewhere/else">value 2</option>
</select>
<script>
document.getElementById('my_selection').onchange = function() {
window.location.href = this.children[this.selectedIndex].getAttribute('href');
}
</script>

render a individual field in a form-inline using 'as_crispy_field'

I need to render individual fields from my Form so I use the filter |as_crispy_field from crispy-forms and use bootstrap 3 for the style but I need to do it in a form-inline like the first example here bootstrap example page so I tried to do it like this:
template.html
<form class="form-inline">{% csrf_token %}
{{ form.name|as_crispy_field }}
</form>
But the label shows above the TextInput field and not in-line as I need. How can I do this using |as_crispy_field?
EDIT: Here is the HTML after the render with crispy
<form class="form-inline"><input type='hidden' name='csrfmiddlewaretoken' value='****...' />
<div id="div_id_name" class="form-group">
<label for="id_name" class="control-label requiredField">
Name<span class="asteriskField">*</span>
</label>
<div class="controls ">
<input class="form-control textinput textInput form-control" id="id_name" maxlength="100" name="name" type="text" />
</div>
</div>
</form>
The one you linked to, with the labels on the left of the fields, is called "form-horizontal" in Crispy. It is explained here. You need to set these helper properties
helper.form_class = 'form-horizontal'
helper.label_class = 'col-lg-2'
helper.field_class = 'col-lg-8'
Actual inline forms, with the label displayed inside the fields are right below on the same page. You only need to set two helper properties
helper.form_class = 'form-inline'
helper.field_template = 'bootstrap3/layout/inline_field.html'
That should do it, if I understood your question correctly.

How to setup the initial value in select control?

I'm trying to setting up a select control on a form, but not achieving the expected results. For me, the strangest thing is it working in the previous control, same type.
This is the function involved:
class ProofMSPE(CrearEvidencia):
model = VRL02
form_class = VRL02Form
def get_form(self, form_class):
form = super(ProofMSPE, self).get_form(form_class)
form.fields['miembro'].queryset = self.pipol
if self.pipol.count() == 1:
form.fields['miembro'].widget.initial = [self.pipol[0].id]
form.fields['meta'].initial = self.meta
form.fields['meta'].widget.attrs['disabled'] = True
return form
The meta's control is select and I got the expected behavior, ie automatically selects an initial value (form.fields['meta'].initial = self.meta and inthe next lines, it disabled (form.fields ['meta']. widget.attrs ['disabled'] = True). This is the output in the rendered template:
<!-- begin meta-->
<div class="row">
<div class="col s12 input-field">
<select id="id_meta" name="meta" disabled>
<option value="">---------</option>
<option value="1" selected="selected">JOCE-1</option>
<option value="2">VEL-1</option>
<option value="3">VEL-2</option>
<option value="4">VEL-3</option>
</select>
<label for="id_meta">Evidencia para la meta</label>
</div>
</div>
<!-- end ./meta -->
On the other hand, with the pipol field I'm unable to get the same result. The difference, by the way, is this field has some logic: I get a filtered list of people with same criteria and the widget is create whit this list (form.fields['miembro'].queryset = self.pipol).
So far so good, but if the queryset has only one result (if self.pipol.count () == 1 :) I want that this one to be used as inital value (form.fields ['member']. Widget.initial = [self .pipol [0] .id]), but this is not working.
This is what appears when the template is rendered:
<!-- begin pipol-->
<div class="row">
<div class="col s12 input-field">
<select id="id_miembro" name="miembro">
<option value="" selected="selected">---------</option>
<option value="2">***#***.mx</option>
</select>
<label for="id_miembro">Seleccione el usuario</label>
</div>
</div>
<!-- end ./pipol -->
Thanks for your time.
You have to set the initial value to the form.field['miembro'] and not the widget, like you did with form.fields['meta'].
def get_form(self, form_class):
form = super(ProofMSPE, self).get_form(form_class)
form.fields['miembro'].queryset = self.pipol
if self.pipol.count() == 1:
# this line here
form.fields['miembro'].initial = self.pipol[0]
form.fields['meta'].initial = self.meta
form.fields['meta'].widget.attrs['disabled'] = True
return form
Select output would be:
<select id="id_miembro" name="miembro">
<option value="">---------</option>
<option value="2" selected="selected">***#***.mx</option>
</select>

bootstrap styling not working with django floppyforms

I am switching from Django Crispy Forms to Floppy Forms, but my desired Bootstrap styling appears to be lost; now it just looks like a plain unstyled form.
Crispy
Here is what I had with Crispy Forms's Bootstrap template pack:
Here was the generated source:
<div id="div_id_sent_amount" class="form-group has-error">
<label for="id_sent_amount" class="control-label requiredField">How much would you like to give?
<span class="asteriskField">*</span>
</label>
<div class="controls ">
<select class="select form-control" id="id_sent_amount" name="sent_amount"><option value="" selected="selected">---------</option><option value="0.00">$0.00</option><option value="0.05">$0.05</option><option value="0.10">$0.10</option></select>
<span id="error_1_id_sent_amount" class="help-block"><strong>This field is required.</strong></span></div>
</div>
Floppy
Here is what I get with Floppy using the Bootstrap layout here.
Here is the generated source:
<div class="form-group error">
<label class="col-sm-4 control-label" for="id_sent_amount">Sent amount <span class="required">*</span>:</label>
<div class="controls col-sm-8 field-sent_amount">
<select id="id_sent_amount" name="sent_amount">
<option value="" selected="selected">---------</option>
<option value="0.00">$0.00</option>
<option value="0.05">$0.05</option>
<option value="0.10">$0.10</option>
</select>
<ul class="errorlist"><li>This field is required.</li></ul>
</div><!--- .controls -->
Any ideas on what I am missing?
floppyforms just provides easier layout and widget control, it does not automatically enable bootstrap styling.
For that, you have to do a bit of work as detailed in the documentation.
In summary, you have to create these templates:
floppyforms/templates/floppyforms/layouts/bootstrap.html
floppyforms/templates/floppyforms/rows/bootstrap.html
floppyforms/templates/floppyforms/layouts/default.html
floppyforms/templates/floppyforms/errors.html
Fill them with bootstrap-specific styling (examples are provided in the documentation).
Keep in mind the examples are for an older version of bootstrap; you might want to update the templates with the current version of bootstrap.
You can edit the templates by hand to bring them up to date, or use django-floppyforms-bootstrap3 which does exactly what it says - updates the templates for bootstrap3 compatibility.