[Zope3-Users] MultiWidget
Roger Ineichen
dev at projekt01.ch
Sun Jan 18 23:04:56 EST 2009
Hi Christian
> Betreff: [Zope3-Users] MultiWidget
>
> Hi,
>
> the new MultiWidget in z3c.form is great! I like the way
> input errors are reported. Thank you for this!
>
> To help the users of my app a little I was thinking about
> conditions for the the add and remove buttons. I think the
> old tuple-sequence widget in zope.app.form had such a
> feature. I want the add button to appear only if the number
> of subwidgets is below the max_length in the schema. And the
> remove button (and even the select boxes) should only appear
> if the number of subwidgets exceeds the min_length of the
> schema or zero. -- Well, OK, one might run into an inregular
> state when selecting several widgets for removal so that the
> min_length is violated. But, at least there should not be a
> remove button if the number of subwidgets equals zero, and no
> add button should appear if the number of subwidgets equals
> (or exceeds) max_length.
>
> To achive this I started with conditions for the buttons. But
> the problem is that the button conditions are checked very
> early during the setup of the widget when one can't yet get
> the number of subwidgets form '_value'-attribute or
> 'widgets'-attribute of the MultiWidget instance.
> So the more general question is: How would one check button
> conditions that depend on a widget's state (number of
> subwidgets, values...)?
>
> Do you have you a hint for me?
Try to call updateActions *again* after action.execute get called.
def update(self):
self.updateWidgets()
self.updateActions()
self.actions.execute()
# update action conditions they get probably changed by execute
self.updateActions()
btw, I will review the form update part again because
I think we need more hooks if it comes to update widgets,
actions and conditions.
I think your usecase is very good starting point for take
another look at this part.
Probably a possible new hooks could be updateActionCondition()
which get called after action.execute()
Regards
Roger Ineichen
_____________________________
END OF MESSAGE
> I code I was trying:
>
> import zope.interface
> from z3c.form import widget, button, interfaces from
> z3c.form.browser import multi from zope.i18n import translate
> import zope.i18nmessageid
>
> _ = zope.i18nmessageid.MessageFactory("zope")
>
>
> class MultiWidget(multi.MultiWidget):
>
> buttons = button.Buttons() # reset buttons
>
> showLabel = False
>
> def addButtonLabel(self):
> button_label = _('Add %s')
> button_label = translate(button_label, context=self.request,
> default=button_label)
> title = getattr(self.field.value_type, 'title', _(u"an item"))
> title = translate(title, context=self.request)
> return button_label % title
>
> @button.buttonAndHandler(_(u"Add an item"),
> name = "add",
> condition = lambda form: form.needAdd(),
> )
> def handleAdd(self, action):
> self.appendAddingWidget()
>
> def needAdd(self):
> # TODO: this gets called before the widgets are updated and we
> # still have self._value == []. So always True is returned
> max_length = getattr(self.field.value_type,
> 'max_lenght', None)
> if max_length is None:
> return True
> else:
> return len(self._value) < max_length
>
> @button.buttonAndHandler(_("remove-selected-items",
> u"Remove selected items"),
> name = "remove",
> condition = lambda form:
> form.needRemove(),
> )
> def handleRemove(self, action):
> """see z3c.form.browser.multi.MultiWidget.handleRemove()"""
> self.widgets = [widget for widget in self.widgets
> if ('%s.remove' % (widget.name)) not
> in self.request]
> self.value = [widget.value for widget in self.widgets]
>
> def needRemove(self):
> # TODO: This gets called before the widgets are updated and
> # len(self._value) == 0.
> min_length = getattr(self.field.value_type, 'min_length', 0)
> return len(self._value) > min_length
>
> def updateActions(self):
> """Use as a hook to make a nice add button label."""
> self.buttons['add'].title = self.addButtonLabel()
> super(MultiWidget, self).updateActions()
>
>
> @zope.interface.implementer(interfaces.IFieldWidget)
> def multiFieldWidgetFactory(field, request):
> return widget.FieldWidget(field, MultiWidget(request))
>
>
> @zope.interface.implementer (interfaces.IFieldWidget) def
> MultiFieldWidget(field, value_type, request):
> return multiFieldWidgetFactory(field, request)
>
>
> Regards,
> Christian
> _______________________________________________
> Zope3-users mailing list
> Zope3-users at zope.org
> http://mail.zope.org/mailman/listinfo/zope3-users
>
More information about the Zope3-users
mailing list