Skip to content

Commit

Permalink
Add support for refreshing actions after execution. Needs review.
Browse files Browse the repository at this point in the history
Update translations, as the change above introduced some new interface description strings.
  • Loading branch information
nadako committed Feb 21, 2009
1 parent 0f25444 commit a5e1dab
Show file tree
Hide file tree
Showing 11 changed files with 458 additions and 272 deletions.
5 changes: 5 additions & 0 deletions CHANGES.txt
Expand Up @@ -5,6 +5,11 @@ CHANGES
Version 2.0.0 (unreleased)
--------------------------

- Feature: Add support for refreshing actions after their execution. This
is useful when button action conditions are changing as a result of
action execution. All you need is to set the ``refreshActions`` flag
of the form to True in your action handler.

- Bug: FieldWidgets update where appending keys and values within each
update call. Now the util.Manager uses a UniqueOrderedKeys implementation
which will ensure that we can't add duplicted manager keys. The implementation
Expand Down
8 changes: 7 additions & 1 deletion src/z3c/form/form.py
Expand Up @@ -160,7 +160,8 @@ class DisplayForm(BaseForm):
class Form(BaseForm):
"""The Form."""
zope.interface.implements(
interfaces.IInputForm, interfaces.IButtonForm, interfaces.IHandlerForm)
interfaces.IInputForm, interfaces.IButtonForm,
interfaces.IHandlerForm, interfaces.IActionForm)

buttons = button.Buttons()

Expand All @@ -169,6 +170,9 @@ class Form(BaseForm):
acceptCharset = FieldProperty(interfaces.IInputForm['acceptCharset'])
accept = FieldProperty(interfaces.IInputForm['accept'])

actions = FieldProperty(interfaces.IActionForm['actions'])
refreshActions = FieldProperty(interfaces.IActionForm['refreshActions'])

@property
def action(self):
"""See interfaces.IInputForm"""
Expand All @@ -190,6 +194,8 @@ def update(self):
super(Form, self).update()
self.updateActions()
self.actions.execute()
if self.refreshActions:
self.updateActions()

def __call__(self):
self.update()
Expand Down
64 changes: 64 additions & 0 deletions src/z3c/form/form.txt
Expand Up @@ -1439,6 +1439,70 @@ In some cases the data converter for a field-widget pair returns the
<Person u'Roger Ineichen'>


Refreshing actions
------------------

Sometimes, it's useful to update actions again after executing them,
because some conditions could have changed. For example, imagine
we have a sequence edit form that has a delete button. We don't
want to show delete button when the sequence is empty. The button
condition would handle this, but what if the sequence becomes empty
as a result of execution of the delete action that was available?
In that case we want to refresh our actions to new conditions to make
our delete button not visible anymore. The ``refreshActions`` form
variable is intended to handle this case.

Let's create a simple form with an action that clears our context
sequence.

>>> class SequenceForm(form.Form):
...
... @button.buttonAndHandler(u'Empty', condition=lambda form:bool(form.context))
... def handleEmpty(self, action):
... self.context[:] = []
... self.refreshActions = True

First, let's illustrate simple cases, when no button is pressed.
The button will be available when context is not empty.

>>> context = [1, 2, 3, 4]
>>> request = TestRequest()
>>> myForm = SequenceForm(context, request)
>>> myForm.update()
>>> addTemplate(myForm)
>>> print testing.render(myForm, './/xmlns:div[@class="action"]')
<div class="action">
<input type="submit" id="form-buttons-empty" name="form.buttons.empty"
class="submit-widget button-field" value="Empty" />
</div>

The button will not be available when the context is empty.

>>> context = []
>>> request = TestRequest()
>>> myForm = SequenceForm(context, request)
>>> myForm.update()
>>> addTemplate(myForm)
>>> print testing.render(myForm, './/xmlns:form')
<form action=".">
</form>

Now, the most interesting case when context is not empty, but becomes
empty as a result of pressing the "empty" button. We set the
``refreshActions`` flag in the action handler, so our actions should
be updated to new conditions.

>>> context = [1, 2, 3, 4, 5]
>>> request = TestRequest(form={
... 'form.buttons.empty': u'Empty'}
... )
>>> myForm = SequenceForm(context, request)
>>> myForm.update()
>>> addTemplate(myForm)
>>> print testing.render(myForm, './/xmlns:form')
<form action=".">
</form>

Integration tests
-----------------

Expand Down
2 changes: 2 additions & 0 deletions src/z3c/form/group.py
Expand Up @@ -95,3 +95,5 @@ def update(self):
self.groups = tuple(groups)
self.updateActions()
self.actions.execute()
if self.refreshActions:
self.updateActions()
17 changes: 17 additions & 0 deletions src/z3c/form/interfaces.py
Expand Up @@ -786,6 +786,23 @@ class IHandlerForm(zope.interface.Interface):
required=True)


class IActionForm(zope.interface.Interface):
"""A form that stores executable actions"""

actions = zope.schema.Object(
title=_('Actions'),
description=_('A list of actons defined on the form'),
schema=IActions,
required=True)

refreshActions = zope.schema.Bool(
title=_('Refresh actions'),
description=_('A flag, when set, causes form actions to be '
'updated again after their execution.'),
default=False,
required=True)


class IContextAware(zope.interface.Interface):
"""Offers a context attribute.
Expand Down

0 comments on commit a5e1dab

Please sign in to comment.