I'm thinking about the DRY way to use field labels for placeholder attribute of my <input>
HTML elements. I'm using django-crispy-forms
.
Right now I have:
class FilterForm(Form):
query = CharField(max_length=50, label='', required=False)
def __init__(self, data=None, files=None, **kwargs):
self.helper = FormHelper()
self.helper.layout = Layout(
Field('query', placeholder='Search ...'),
)
super(FilterForm, self).__init__(data, files, **kwargs)
I'd prefer, however, not to have to set label and placeholder separately, as this for will eventually have many more fields and it's quite verbose.
What are your suggestions?
A DRY solution could be achieved with this __init__ method:
def __init__(self, *args, **kwargs):
super(FilterForm, self).__init__(*args, **kwargs)
helper = self.helper = FormHelper()
# Moving field labels into placeholders
layout = helper.layout = Layout()
for field_name, field in self.fields.items():
layout.append(Field(field_name, placeholder=field.label))
helper.form_show_labels = False
Currently, hiding labels can be achieved by using the bootstrap helper attribute below:
self.helper.form_show_labels = False
Default set to True. It decides wether to render or not form’s fields labels.
You still need to define the placeholder using the Field layout object:
Field('query', placeholder='Search ...'),
Try this:
class FilterForm(Form):
query = CharField(max_length=50, label='', required=False)
def __init__(self, data=None, files=None, **kwargs):
self.helper = FormHelper()
self.helper.layout = Layout(
Field('query', placeholder=kwargs.pop('query_placeholder', 'random text')),
)
super(FilterForm, self).__init__(data, files, **kwargs)
You can add extra attributes to your form fields by using:
query = CharField(widget=forms.TextInput(attrs={'placeholder':'Search..'}),
max_length=50, label='', required=False)
This DRY solution doesn't require modification of the layout. I suggest making it a mixin:
class MyForm(Form):
_placeholders = {
'fieldname': 'fieldname placeholder',
}
def __init__(self, *args, **kwargs):
# Assign placeholder to widget of fields
# listed in self._placeholders.
for field_name, field in self.fields.items():
if field_name in self._placeholders:
self.fields[field_name].widget.attrs['placeholder'] = \
self._placeholders[field_name]
super(MyForm, self).__init__(*args, **kwargs)
There is the widgets field if you want more control
class PostForm(forms.ModelForm):
class Meta:
model = Post
widgets = {
'comment': forms.Textarea(attrs={'rows': 6, 'placeholder': 'Enter your comments'}),
}
labels = {
"private": "Keep Private",
}
exclude = ['response', 'display']
I ended up just hiding the field labels using css. It's a bit hackish, but works. I still used placeholder="your label" to define the placeholders though.