collective / collective.z3cform.datagridfield

Datagrid Field for z3c.forms
https://pypi.org/project/collective.z3cform.datagridfield/
8 stars 28 forks source link

[Documentation] Add a working example for Dexterity (Plone) #185

Open yurj opened 6 months ago

yurj commented 6 months ago

Hi!

the documentation in collective.z3cform.datagridfield is add/edit form oriented. What about a common integrator that want to add a DGF field in a content type?

What I've found it works (with widget parameters customization):

ITableRowSchema:

class ITableRowSchema(model.Schema):
    servizio = schema.TextLine(title=u"Servizio")
    telefono = schema.TextLine(title=u"Telefono")
    email = schema.TextLine(title=u"Email")

and in widget.py:

@adapter(schema.interfaces.IField, form.interfaces)
@implementer(form.interfaces.IFieldWidget)
def ServiziDataGridFieldFactory(field, request):
    """
    A special widget constructor setting up widget parameters for DGF.
    """
    widget = DataGridFieldFactory(field, request)
    widget.allow_reorder = True
    return widget

If you don't need widget customization, it is simpler:

What works but you cannot change widget defaults with hints:

xml schema:

<field name="servizi" type="zope.schema.List"> <!-- here you can put name="table", works the same =) -->
<description>...</description>
<title>Servizi</title>
<value_type type="collective.z3cform.datagridfield.DictRow">
<schema>myproduct.interfaces.ITableRowSchema</schema>
</value_type>
<form:widget type="collective.z3cform.datagridfield.datagridfield.DataGridFieldWidgetFactory" />
</field>

widget interfaces:

from collective.z3cform.datagridfield.datagridfield import DataGridFieldFactory
from collective.z3cform.datagridfield.row import DictRow
from plone.autoform.directives import widget
from plone.autoform.form import AutoExtensibleForm
from z3c.form import form
from zope import interface
from zope import schema

class ITableRowSchema(interface.Interface):
    servizio = schema.TextLine(title=u"Servizio")
    telefono = schema.TextLine(title=u"Telefono")
    email = schema.TextLine(title=u"Email")

class IFormSchema(interface.Interface):
    servizi = schema.TextLine(title=u"Servizi")
    table = schema.List(
        title=u"Servizi",
        value_type=DictRow(
            title=u"servicerow",
            schema=ITableRowSchema,
        ),
    )

    widget("table", DataGridFieldFactory, allow_reorder=True,) # <- you can comment it, does nothing in my experience.

Note: here we have "servizi" + "table" but "it works". It works also if you change "table" in the xml schema above with "servizi", this is totally obscure to me, sorry my fault.

I'm aware it should work without behaviours (see: https://github.com/kombinat/collective.coursetool/blob/main/src/collective/coursetool/content/course.py#L57) but I still have to get it after several hours of reading and breakpoints (my fault).

Another missing piece (my opinion) is some hints on how to manage schemas (xml, profiles, object schema from model.schema).

petschki commented 5 months ago

With plone.autoform schema hints its event simpler to customize widget attributes. See the new enhanced demo module in my latest PR ... I'll extend this with schema.xml files too to outline the usage of DGF better for behaviors, contenttypes, controlpanels etc ... https://github.com/collective/collective.z3cform.datagridfield/blob/vocabulary-lookup-fix/src/collective/z3cform/datagridfield/demo/content.py#L46

I've opted out the demo module, so it has to be included explicitely in buildout with

[instance]
zcml +=
    collective.z3cform.datagridfield.demo

or in your integration packages zcml with

<include package="collective.z3cform.datagridfield.demo" />

then you can install the demo package in the addons and you have the behavior registered for Document and a new DGFTest contenttype ... I'll come up with some more tests too.

yurj commented 5 months ago

That's very good. I'm still using the approach above but this is definitively the way to go. Thanks!