yurj
(Yuri)
July 29, 2024, 10:55am
1
Hi!
is is possible to add a read only field to Easyform? My use case it to display something in the form (at the begin of the form for example) based on some site parameters. I can have a text field with a default value but it is rendered as an input field. The label and advanced label fields ignores the override fields, they're just static.
mtrebron
(Norbert )
July 29, 2024, 1:08pm
2
Given that
<field name="intro_text"
type="zope.schema.TextLine">
<default>My text</default>
<readonly>True</readonly>
</field>
causes the field to not be displayed, I would use some custom CSS to apply your "read-only "styling and use a default factory to populate the field.
<field name="intro_text"
type="zope.schema.TextLine"
easyform:css_class="textline-readonly">
<defaultFactory>my_package.interfaces.intro_text_default</defaultFactory>
</field>
EDIT, you want to use form:mode
<field form:mode="display" name="intro_text" type="zope.schema.TextLine" >
<default>My text</default>
</field>
1 Like
yurj
(Yuri)
July 29, 2024, 2:13pm
3
Thanks!
This is my defaultFactory:
@provider(IDefaultFactory)
def intro_text_default(self):
return 'AAA'
It works but there's no parameter in the function... no self, context or other else.
yurj
(Yuri)
July 29, 2024, 2:17pm
4
if I do:
@provider(IContextAwareDefaultFactory)
def intro_text_default(context):
return 'AAA' + str(context)
context is None, this prints 'AAANone'
but with breakpoint():
utils.py(143)intro_text_default()
-> return 'AAA' + str(context)
(Pdb) pp context
<EasyForm at /xxxx/myform>
(Pdb) pp str(context)
<EasyForm at /xxxx/myform>
:-/
mtrebron
(Norbert )
July 29, 2024, 2:21pm
5
I see you are already using IContextAwareDefaultFactory
- maybe you have to get the context "out of thin air" with getSite()
or its plone.api equivalent?
yurj
(Yuri)
July 29, 2024, 2:27pm
6
I get it. The defaultFactory is called 3 times. The first 2 time context is there, the third one (the one used by the model) returns None. So I get None at the end.
This is my supermodel xml:
<field form:mode="display" name="intro_text" type="zope.schema.TextLine" easyform:css_class="textline-readonly">
<defaultFactory>myaddon.utils.intro_text_default</defaultFactory>
</field>
(rendering the dexterity control panel, the function is called 2 times, not 3.
in the dexterity ttw field editor I get as default value:
AAA
mtrebron
(Norbert )
July 29, 2024, 2:31pm
7
Be aware that modifying the form with the GUI will replace the factory with its static value.
yurj
(Yuri)
July 29, 2024, 2:38pm
8
Continuing in the debugger, I end here after the third call:
zope/schema/_bootstrapfields.py(108)
103 if IContextAwareDefaultFactory.providedBy(defaultFactory):
104 value = defaultFactory(inst.context)
105 else:
106 value = defaultFactory()
Also adding alsoProvides(IContextAwareDefaultFactory)
inside the function does not work, I always get None at the end.
Be aware that modifying the form with the GUI will replace the factory with its static value.
I saved the xml directly and it is still there.
:-/
mtrebron
(Norbert )
July 29, 2024, 2:47pm
9
I tend to short-circuit these types of deep z3c.form mysteries with something like (or similar):
from zope.globalrequest import getRequest
def getContext():
request = getRequest()
published = request.get("PUBLISHED", None)
context = getattr(published, "__parent__", None)
return context
2 Likes
yurj
(Yuri)
July 29, 2024, 3:10pm
10
Using getContext above works!
The question is: why you Plone are you asking me contextaware this and that, while context and request are already there? LOL
Looking at the code seems a problem of easyform superAdapter
. Also the code is called 3 times... magic of widget "update()".
Anyway thanks!
1 Like
mtrebron
(Norbert )
July 29, 2024, 3:32pm
11
Happy it worked!
Try this with a DataGridField... Better not!