Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using collective.z3cform.datagridfield with Dexterity

I'm somewhat of a newbie to Plone and I'm attempting to use DataGridField with Dexterity. The goal is to use Plone 4.1 to publish the results of a usability study on our intranet. I've created a custom document type (called an Interaction) and I want to use datagrid for one of the fields to model a table containing two columns showing a summary of findings.

As per the instructions listed at collective.z3cform.datagridfield I've successfully added the collective.z3cform.datagrid egg to the list of eggs in my buildout and I can see the new Add-on appear as Active in my list of Add-ons for my site. I've created a simple schema Python module which describes a document showing findings from a usability study I'm documenting:

from five import grok
from zope import schema
from zope import interface

from plone.directives import form

from plonetheme.mytheme import InteractionMessageFactory as _

from plone.app.textfield import RichText

from z3c.form import field, button
from Products.CMFCore.interfaces import IFolderish

from collective.z3cform.datagridfield import DataGridFieldFactory, DictRow

class IFinding(interface.Interface):
    summary = schema.TextLine(title=_(u"Summary"))
    percentage = schema.TextLine(title=_(u"Percentage"))

class IInteraction(form.Schema):

    findings = schema.List(
        title=_(u"Overview of findings"),
        required=False,
        value_type=DictRow(
            title=_(u"Finding"),
            schema=IFinding
            )
        )

class EditForm(form.EditForm):
    grok.context(IInteraction)
    grok.require('zope2.View')
    fields = field.Fields(IInteraction)

    fields['findings'].widgetFactory = DataGridFieldFactory

I've registered my new Interaction content type by adding a line to profiles/default/types.xml:

<?xml version="1.0"?>
<object meta_type="Plone Types Tool" name="portal_types">
<property name="title">Controls the available content types in your portal</property>
<object meta_type="Dexterity FTI" name="interaction" />
<!-- -*- extra stuff goes here -*- -->
</object>

For completeness, I've also included the corresponding profiles/default/types/interaction.xml file:

<?xml version="1.0"?>
<object name="interaction" meta_type="Dexterity FTI"
   xmlns:i18n="http://xml.zope.org/namespaces/i18n">
 <property name="title">Interaction</property>
 <property name="description">An item in the interactions dictionary</property>
 <property name="icon_expr">string:${portal_url}/document_icon.png</property>
 <property name="factory">interaction</property>
 <property name="link_target"></property>
 <property name="immediate_view">view</property>
 <property name="global_allow">True</property>
 <property name="filter_content_types">True</property>
 <property name="allowed_content_types"/>
 <property name="allow_discussion">False</property>
 <property name="default_view">view</property>
 <property name="view_methods">
  <element value="view"/>
 </property>
 <property name="default_view_fallback">False</property>
 <property name="add_permission">cmf.AddPortalContent</property>
 <property name="klass">plone.dexterity.content.Item</property>
 <property name="behaviors">
  <element value="plone.app.dexterity.behaviors.metadata.IDublinCore"/>
  <element value="plone.app.content.interfaces.INameFromTitle"/>
  <element value="collective.flowplayer.behaviors.IFlowplayerFile"/>
 </property>
 <property name="schema">plonetheme.mytheme.interaction.IInteraction</property>

 <property name="model_file"></property>
 <alias from="(Default)" to="(dynamic view)"/>
 <alias from="edit" to="@@edit"/>
 <alias from="sharing" to="@@sharing"/>
 <alias from="view" to="(selected layout)"/>
 <action title="View" action_id="view" category="object" condition_expr=""
    icon_expr="" link_target="" url_expr="string:${object_url}"
    visible="True">
  <permission value="View"/>
 </action>
 <action title="Edit" action_id="edit" category="object" condition_expr=""
    icon_expr="" link_target="" url_expr="string:${object_url}/edit"
    visible="True">
  <permission value="Modify portal content"/>
 </action>
</object>

When I go to the Add form for my Interaction custom type, I get a standard Dexterity List item Add/Remove widget rather than the datagrid table widget I've seen in the collective.z3cform.datagrid_demo examples. When I attempt to save the custom type the Dexterity list widget displays a validation error 'The system could not process the given value.'

Is there any other code I need to add? Do I need to override the Dexterity Add/EditForm view templates?

like image 547
Andrew Heckford Avatar asked Nov 28 '11 19:11

Andrew Heckford


3 Answers

You're doing things as documented, but it won't work. This is a known issue:

http://code.google.com/p/dexterity/issues/detail?id=246

like image 142
Marcel Maré Avatar answered Nov 12 '22 21:11

Marcel Maré


try using Dexterity form hints:

...
from zope import schema
from zope.interface import Interface

from plone.directives import form

from collective.z3cform.datagridfield import DataGridFieldFactory, DictRow

from plonetheme.mytheme import InteractionMessageFactory as _
...


class IFindingRow(Interface):
    summary = schema.TextLine(title=_(u'Summary'), 
                              required=False)
    percentage = schema.TextLine(title=_(u'Percentage'), 
                                 required=False)


class IInteraction(form.Schema):

    ...

    form.widget(findings=DataGridFieldFactory)
    findings= schema.List(
            title=_(u"Overview of findings"),
            value_type=DictRow(title=_(u"Finding"), 
                               schema=IFindingRow),
            required=False,                      
        )
like image 43
Rigel Di Scala Avatar answered Nov 12 '22 20:11

Rigel Di Scala


This works for me in Plone 5.0.4

from zope import schema 
from zope.interface import Interface
from plone.supermodel import model
from plone.autoform import directives
from collective.z3cform.datagridfield import DataGridFieldFactory, DictRow
from plonetheme.mytheme import InteractionMessageFactory as _

class IFindingRow(Interface):
    summary = schema.TextLine(title=_(u'Summary'), 
                          required=False)
    percentage = schema.TextLine(title=_(u'Percentage'), 
                             required=False)


class IInteraction(model.Schema):
    directives.widget(findings=DataGridFieldFactory)
    findings= schema.List(
        title=_(u"Overview of findings"),
        value_type=DictRow(title=_(u"Finding"), 
                           schema=IFindingRow),
        required=False,                      
    )
like image 38
tareqalam Avatar answered Nov 12 '22 20:11

tareqalam