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? 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@zope.org http://mail.zope.org/mailman/listinfo/zope3-users