I have a need to save several TextLine field values entered in a p.a.z3cform form in uppercase. On the frontend, I am already using CSS text-transform. What is needed in the backend to do the transformation on save? My type is defined as follows:
class IApplicationForm(model.Schema):
last_name = schema.TextLine(
title="Last Name",
required=False,
)
first_name = schema.TextLine(
title="First Name",
required=False,
)
...
@implementer(IApplicationForm)
class ApplicationForm(Container):
You could use a dataconverter for this. Either apply the conversion to all TextLine fields, or create a UppercaseTextLine field that derives from schema.TextLine.
If I understand correctly, I will need to create a custom schema if I want to selectively apply the uppercase format. But if I want the format to apply to all TextLine field, I will just need a custom widget data converter? It is not enough to create a custom widget (with appropriate converter) and specify that the field use this custom widget?
Thank you for the tip. I made it work by creating a custom widget and dataconverter. Below is what I did.
interfaces.py
from plone.app.z3cform.interfaces import ITextWidget
class IUppercaseTextWidget(ITextWidget):
"""Marker interface for uppercase text widget"""
uppercase_text.py
from myapp.common.interfaces import IUppercaseTextWidget
from plone.app.z3cform.converters import BaseDataConverter
from z3c.form.browser.text import TextWidget
from z3c.form.interfaces import IFieldWidget
from z3c.form.widget import FieldWidget
from zope.component import adapter
from zope.interface import implementer
from zope.schema.interfaces import ITextLine
@implementer(IUppercaseTextWidget)
class UppercaseTextWidget(TextWidget):
"""Text widget using uppercase"""
klass = 'uppercase-text-widget'
@implementer(IFieldWidget)
def UppercaseTextFieldWidget(field, request):
return FieldWidget(field, UppercaseTextWidget(request))
@adapter(ITextLine, IUppercaseTextWidget)
class UppercaseTextDataConverter(BaseDataConverter):
def toFieldValue(self, value):
if self._strip_value and isinstance(value, str):
stripped = value.strip()
value = stripped.upper()
if value == '':
return self.field.missing_value
return self.field.fromUnicode(value)
from myapp.common.widgets.uppercase_text import UppercaseTextFieldWidget
class IApplicationForm(model.Schema):
directives.widget("last_name", UppercaseTextFieldWidget)
last_name = schema.TextLine(
title="Last Name",
required=False,
)
The uppercase transformation is only applied to fields that are using UppercaseTextFieldWidget. Then in the frontend form, I use text-transformation on the class "uppercase-text-widget"