Custom Style of a textarea.

264 views
Skip to first unread message

Francisco García

unread,
Oct 4, 2013, 1:14:33 PM10/4/13
to web...@googlegroups.com
Hello all,

I am loading a form from a database table, with CRUD or SQLFORM (It is the same for me).
This form contains text fields and textarea fields between others.

Now, I need to change in the views the class of all textareas,  from class="text"  to class="myclass"
How can I do this from controllers or views?   (I can't edit any css file).

I am trying with form.custom.widget  but I can't change it.
I'm not sure if it is something simple, or it is impossible to do this way.


Thank you in advance.
Regards,
Francisco

Ykä Marjanen

unread,
Oct 5, 2013, 3:24:59 AM10/5/13
to web...@googlegroups.com
Hi Francisco,

happy to help you, as I've gone a 4 day intensive bootstrap 3 integration to web2py and learned a lot about customizing the views and forms. This might not be the best (or only) solution, but has worked well for me:

- Web2py form includes classes based on their type, which I recommend to keep, if you want any added web2py functionality.
- You need to use custom form style (form.custom.begin) and then manipulate each widget separately (or all of them in a for loop)

Here's my form code in a view (controller is not modified). In this form I have added "form-control" class of bootstrap 3 and kept the original class as well. For textarea you can do "form.custom.widget.textfield['_rows'] = 3" if you want to make a smaller textarea.

<<<
<form action="" enctype="multipart/form-data" method="post" role="form">
<div class="form-group">
                    {{form.custom.widget.campaign['_class'] = 'generic-widget form-control'}}
                    {{form.custom.widget.topic['_class'] = 'string form-control'}}
                    {{form.custom.widget.topic['_placeholder'] = 'Idea topic'}}
                    {{form.custom.widget.description['_class'] = 'text form-control'}}
                    {{form.custom.widget.description['_placeholder'] = 'Idea description'}}
                    <div class="form-group">
                        <label for="exampleSelect">Select a campaign</label>
                        {{=form.custom.widget.campaign}}
                    </div>
                    <div class="form-group">
                        <label for="exampleInputTopic">Input idea topic and description</label>
                        {{=form.custom.widget.topic}}
                    </div>
                    <div class="form-group">
                        {{=form.custom.widget.description}}
                    </div>
                    <button type="submit" class="btn btn-primary">Submit your idea</button>
                </div>
{{=form.custom.end}}

<<<<

Ykä

Paolo Caruccio

unread,
Oct 5, 2013, 3:51:26 AM10/5/13
to web...@googlegroups.com
By using server-side DOM and parsing ( see the book http://www.web2py.com/books/default/chapter/29/05/the-views?search=DOM#Server-side-DOM-and-parsing ) you could collect all textareas and after make a loop on the collection to change the css class. For example in your controller

all_textareas = the_form.elements('textarea.text')

for a_textarea in all_textareas:
    a_textarea
['_class'] = "myclass"

Francisco García

unread,
Oct 6, 2013, 3:31:19 PM10/6/13
to web...@googlegroups.com
Hello Ykä and Paolo,

Your answers are very useful for me. The problem is solved.
All I needed was this sentence:

form.custom.widget.FIELD['_class'] = 'text myclass'}

Thank you for your fast answer.
Regards.

Ykä Marjanen

unread,
Oct 7, 2013, 6:32:53 AM10/7/13
to web...@googlegroups.com
Glad to help back, as I've gotten so much help from here.

If you like to have a more generic code to add your classes to the form objects, you can use the code below. It will add a new class to all elements while keeping the web2py classes. I think you could even add this to the layout with "try"-statement, so anytime you use any form, it would include new classes.

<!-- Additing bootstrap 3 classes to web2py form-->
{{for element in form.elements():}}
    {{if element['_class']:}}
        {{element['_class'] = str(element['_class']) + " form-control"}}
    {{else:}}
        {{element['_class'] = 'form-control'}}
    {{pass}}
{{pass}}

Ykä

Anthony

unread,
Oct 7, 2013, 11:13:32 AM10/7/13
to web...@googlegroups.com
There are multiple ways to handle this, including Javascript on the client side, manipulation of form.custom.widget, the web2py server-side DOM, and custom widgets. Note, when adding a class to an existing element on the server side, you can use the .add_class method, which intelligently handles cases where there is already an existing class.

At the form level, you can use the server-side DOM:

form.elements('textarea', replace=lambda el: el.add_class('form-control'))

The above affects only this particular form.

Another option is to create a custom widget, which works at the table level and therefore affects all forms based on the table:

def text_widget(field, value, text_class='form-control'):
   
return SQLFORM.widgets.text.widget(field, value).add_class(text_class)

db
.define_table('mytable',
   
Field('myfield', 'text', widget=text_widget))

Finally, you could monkey patch the text widget directly, which would affect all text fields in all tables:

SQLFORM.widgets.text._class = 'text form-control'

Anthony
Reply all
Reply to author
Forward
0 new messages