ploneportletz3c.form

Can I use z3c.form on Plone portlets instead of zope.formlib?


What modifications do I need to make considering I have a vanilla ZopeSkel plone3_portlet formlib generated package? Ie:

Can I use it all the way down including five.grok and plone.directives.form?


Solution

  • Yes, you can do that, what you need is the Add/Edit forms... Here's what I did it for a Jarn project, you can use AddForm and EditForm the same way you would use their formlib equvalent:

    from Acquisition import aq_parent, aq_inner
    from plone.app.portlets import PloneMessageFactory as _
    from plone.app.portlets.browser.interfaces import IPortletAddForm
    from plone.app.portlets.browser.interfaces import IPortletEditForm
    from plone.app.portlets.interfaces import IPortletPermissionChecker
    from z3c.form import button
    from z3c.form import form
    from zope.component import getMultiAdapter
    from zope.interface import implements
    
    
    class AddForm(form.AddForm):
        implements(IPortletAddForm)
    
        label = _(u"Configure portlet")
    
        def add(self, object):
            ob = self.context.add(object)
            self._finishedAdd = True
            return ob
    
        def __call__(self):
            IPortletPermissionChecker(aq_parent(aq_inner(self.context)))()
            return super(AddForm, self).__call__()
    
        def nextURL(self):
            addview = aq_parent(aq_inner(self.context))
            context = aq_parent(aq_inner(addview))
            url = str(getMultiAdapter((context, self.request),
                                      name=u"absolute_url"))
            return url + '/@@manage-portlets'
    
        @button.buttonAndHandler(_(u"label_save", default=u"Save"), name='add')
        def handleAdd(self, action):
            data, errors = self.extractData()
            if errors:
                self.status = self.formErrorsMessage
                return
            obj = self.createAndAdd(data)
            if obj is not None:
                # mark only as finished if we get the new object
                self._finishedAdd = True
    
        @button.buttonAndHandler(_(u"label_cancel", default=u"Cancel"),
                                 name='cancel_add')
        def handleCancel(self, action):
            nextURL = self.nextURL()
            if nextURL:
                self.request.response.redirect(nextURL)
            return ''
    
    
    class EditForm(form.EditForm):
        """An edit form for portlets.
        """
    
        implements(IPortletEditForm)
    
        label = _(u"Modify portlet")
    
        def __call__(self):
            IPortletPermissionChecker(aq_parent(aq_inner(self.context)))()
            return super(EditForm, self).__call__()
    
        def nextURL(self):
            editview = aq_parent(aq_inner(self.context))
            context = aq_parent(aq_inner(editview))
            url = str(getMultiAdapter((context, self.request),
                                      name=u"absolute_url"))
            return url + '/@@manage-portlets'
    
        @button.buttonAndHandler(_(u"label_save", default=u"Save"), name='apply')
        def handleSave(self, action):
            data, errors = self.extractData()
            if errors:
                self.status = self.formErrorsMessage
                return
            changes = self.applyChanges(data)
            if changes:
                self.status = "Changes saved"
            else:
                self.status = "No changes"
    
            nextURL = self.nextURL()
            if nextURL:
                self.request.response.redirect(self.nextURL())
            return ''
    
        @button.buttonAndHandler(_(u"label_cancel", default=u"Cancel"),
                                 name='cancel_add')
        def handleCancel(self, action):
            nextURL = self.nextURL()
            if nextURL:
                self.request.response.redirect(nextURL)
            return ''