@@ -120,6 +120,324 @@ schema = IMyForm
120
120
If your form is not bound to an object (such as a Dexterity object), set ` ignoreContext = True ` .
121
121
122
122
123
+ (classic-ui-forms-autoform-label)=
124
+ ## Controlling form presentation
125
+
126
+ Directives can be specified in the schema to control aspects of form presentation.
127
+
128
+ ### Changing a field's display mode
129
+
130
+ A field's widget can be displayed in several "modes":
131
+
132
+ * input - allows the user to enter data into the field
133
+ * display - a read-only indication of the field's value
134
+ * hidden - a record of the field's value that is included only in the HTML source
135
+
136
+ The mode can be controlled using the ` mode ` directive.
137
+
138
+ ``` python
139
+ from plone.supermodel import model
140
+ from plone.autoform import directives as form
141
+
142
+ class IMySchema (model .Schema ):
143
+
144
+ form.mode(secret = ' hidden' )
145
+ form.mode(IEditForm, secret = ' input' )
146
+ secret = schema.TextLine(
147
+ title = u " Secret" ,
148
+ default = u " Secret stuff (except on edit forms)"
149
+ )
150
+ ```
151
+
152
+ In this case the mode for the ` secret ` field is set to 'hidden' for most forms,
153
+ but 'input' for forms that provide the IEditForm interface.
154
+
155
+ The corresponding supermodel XML directive is ` form:mode ` :
156
+
157
+ ``` xml
158
+ <field type =" zope.schema.TextLine"
159
+ name =" secret"
160
+ form : mode =" z3c.form.interfaces.IForm:hidden z3c.form.interfaces.IEditForm:input" >
161
+ <title >Secret</title >
162
+ <description >Secret stuff (except on edit forms)</description >
163
+ </field >
164
+ ```
165
+
166
+ The mode can be specified briefly if it should be the same for all forms:
167
+
168
+ ``` xml
169
+ <field type =" zope.schema.TextLine"
170
+ name =" secret"
171
+ form : mode =" hidden" >
172
+ <title >Secret</title >
173
+ <description >Secret stuff</description >
174
+ </field >
175
+ ```
176
+
177
+ In other words, ` form:mode ` may be either a single mode, or a space-separated
178
+ list of form_interface: mode pairs.
179
+
180
+
181
+ ### Omitting fields
182
+
183
+ A field can be omitted entirely from all forms, or from some forms,
184
+ using the ` omitted ` and ` no_omit ` directives. In this example,
185
+ the ` dummy ` field is omitted from all forms, and the ` edit_only `
186
+ field is omitted from all forms except those that provide the
187
+ IEditForm interface:
188
+
189
+ ``` python
190
+ from z3c.form.interfaces import IEditForm
191
+ from plone.supermodel import model
192
+ from plone.autoform import directives as form
193
+
194
+ class IMySchema (model .Schema ):
195
+
196
+ form.omitted(' dummy' )
197
+ dummy = schema.Text(
198
+ title = u " Dummy"
199
+ )
200
+
201
+ form.omitted(' edit_only' )
202
+ form.no_omit(IEditForm, ' edit_only' )
203
+ edit_only = schema.TextLine(
204
+ title = u ' Only included on edit forms' ,
205
+ )
206
+ ```
207
+
208
+ In supermodel XML, this can be specified as:
209
+
210
+ ``` xml
211
+ <field type =" zope.schema.TextLine"
212
+ name =" dummy"
213
+ form : omitted =" true" >
214
+ <title >Dummy</title >
215
+ </field >
216
+
217
+ <field type =" zope.schema.TextLine"
218
+ name =" edit-only"
219
+ form : omitted =" z3c.form.interfaces.IForm:true z3c.form.interfaces.IEditForm:false" >
220
+ <title >Only included on edit form</title >
221
+ </field >
222
+ ```
223
+
224
+ ` form:omitted ` may be either a single boolean value, or a space-separated
225
+ list of form_interface: boolean pairs.
226
+
227
+
228
+ ### Re-ordering fields
229
+
230
+ A field's position in the form can be influenced using the ` order_before `
231
+ and ` order_after ` directives. In this example, the ` not_last ` field
232
+ is placed before the ` summary ` field even though it is defined afterward:
233
+
234
+ ``` python
235
+ from plone.supermodel import model
236
+ from plone.autoform import directives as form
237
+
238
+ class IMySchema (model .Schema ):
239
+
240
+ summary = schema.Text(
241
+ title = u " Summary" ,
242
+ description = u " Summary of the body" ,
243
+ readonly = True
244
+ )
245
+
246
+ form.order_before(not_last = ' summary' )
247
+ not_last = schema.TextLine(
248
+ title = u " Not last" ,
249
+ )
250
+ ```
251
+
252
+ The value passed to the directive may be either '* ' (indicating before or after
253
+ all fields) or the name of another field. Use ` '.fieldname' ` to refer to
254
+ field in the current schema or a base schema. Prefix with the schema name (e.g.
255
+ ` 'IDublinCore.title' ` ) to refer to a field in another schema. Use an
256
+ unprefixed name to refer to a field in the current or the default schema for
257
+ the form.
258
+
259
+ In supermodel XML, the directives are called ` form:before ` and ` form:after ` .
260
+ For example:
261
+
262
+ ``` xml
263
+ <field type =" zope.schema.TextLine"
264
+ name =" not_last"
265
+ form : before =" *" >
266
+ <title >Not last</title >
267
+ </field >
268
+ ```
269
+
270
+
271
+ ### Organizing fields into fieldsets
272
+
273
+ Fields can be grouped into fieldsets, which will be rendered within an HTML
274
+ ` <fieldset> ` tag. In this example the ` footer ` and ` dummy ` fields
275
+ are placed within the ` extra ` fieldset:
276
+
277
+ ``` python
278
+ from plone.supermodel import model
279
+ from plone.autoform import directives as form
280
+
281
+ class IMySchema (model .Schema ):
282
+
283
+ model.fieldset(' extra' ,
284
+ label = u " Extra info" ,
285
+ fields = [' footer' , ' dummy' ]
286
+ )
287
+
288
+ footer = schema.Text(
289
+ title = u " Footer text" ,
290
+ )
291
+
292
+ dummy = schema.Text(
293
+ title = u " Dummy"
294
+ )
295
+ ```
296
+
297
+ In supermodel XML fieldsets are specified by grouping fields within a
298
+ ` <fieldset> ` tag:
299
+
300
+ ``` xml
301
+ <fieldset name =" extra" label =" Extra info" >
302
+ <field name =" footer" type =" zope.schema.TextLine" >
303
+ <title >Footer text</title >
304
+ </field >
305
+ <field name =" dummy" type =" zope.schema.TextLine" >
306
+ <title >Dummy</title >
307
+ </field >
308
+ </fieldset >
309
+ ```
310
+
311
+
312
+ ### Changing a field's widget
313
+
314
+ Usually, z3c.form picks a widget based on the type of your field.
315
+ You can change the widget using the ` widget ` directive if you want
316
+ users to enter or view data in a different format. For example,
317
+ here we change the widget for the ` human ` field to use yes/no
318
+ radio buttons instead of a checkbox:
319
+
320
+ ``` python
321
+ from plone.supermodel import model
322
+ from plone.autoform import directives as form
323
+ from z3c.form.browser.radio import RadioFieldWidget
324
+
325
+ class IMySchema (model .Schema ):
326
+ form.widget(' human' , RadioFieldWidget)
327
+ human = schema.Bool(
328
+ title = u ' Are you human?' ,
329
+ )
330
+ ```
331
+
332
+ You can also pass widget parameters to control attributes of the
333
+ widget. For example, here we keep the default widget, but
334
+ set a CSS class:
335
+
336
+ ``` python
337
+ from plone.supermodel import model
338
+ from plone.autoform import directives as form
339
+ from z3c.form.browser.radio import RadioWidget
340
+
341
+ class IMySchema (model .Schema ):
342
+ form.widget(' human' , klass = ' annoying' )
343
+ human = schema.Bool(
344
+ title = u ' Are you human?' ,
345
+ )
346
+ ```
347
+
348
+ In supermodel XML the widget is specified using a ` <form:widget> ` tag, which
349
+ can have its own elements specifying parameters::
350
+
351
+ ``` xml
352
+ <field name =" human" type =" zope.schema.TextLine" >
353
+ <title >Are you human?</title >
354
+ <form : widget type =" z3c.form.browser.radio.RadioWidget" >
355
+ <klass >annoying</klass >
356
+ </form : widget >
357
+ </field >
358
+ ```
359
+
360
+ Note: In order to be included in the XML representation of a schema,
361
+ widget parameters must be handled by a WidgetExportImportHandler utility.
362
+ There is a default one which handles the attributes defined in
363
+ ` z3c.form.browser.interfaces.IHTMLFormElement ` .
364
+
365
+ ### Protect a field with a permission
366
+
367
+ By default, fields are included in the form regardless of the user's
368
+ permissions. Fields can be protected using the ` read_permission `
369
+ and ` write_permission ` directives. The read permission is checked when
370
+ the field is in display mode, and the write permission is checked when
371
+ the field is in input mode. The permission should be given with its
372
+ Zope 3-style name (i.e. cmf.ManagePortal rather than 'Manage portal').
373
+
374
+ In this example, the ` secret ` field is protected by the
375
+ ` cmf.ManagePortal ` permission as both a read and write permission.
376
+ This means that in both display and input modes, the field will
377
+ only be included in the form for users who have that permission:
378
+
379
+ ``` python
380
+ from plone.supermodel import model
381
+ from plone.autoform import directives as form
382
+
383
+ class IMySchema (model .Schema ):
384
+ form.read_permission(secret = ' cmf.ManagePortal' )
385
+ form.write_permission(secret = ' cmf.ManagePortal' )
386
+ secret = schema.TextLine(
387
+ title = u ' Secret' ,
388
+ )
389
+ ```
390
+
391
+ In supermodel XML the directives are ` security:read-permission ` and
392
+ ` security:write-permission ` :
393
+
394
+ ``` xml
395
+ <field type =" zope.schema.TextLine"
396
+ name =" secret"
397
+ security : read-permission =" cmf.ManagePortal"
398
+ security : write-permission =" cmf.ManagePortal" >
399
+ <title >Secret</title >
400
+ </field >
401
+ ```
402
+
403
+ ## Display Forms
404
+
405
+
406
+ Sometimes rather than rendering a form for data entry, you want to display
407
+ stored values based on the same schema. This can be done using a "display form."
408
+ The display form renders each field's widget in "display mode," which means
409
+ that it shows the field value in read-only form rather than as a form input.
410
+
411
+ To use the display form, create a view that extends ` WidgetsView ` like this:
412
+
413
+ ``` python
414
+ from plone.autoform.view import WidgetsView
415
+
416
+ class MyView (WidgetsView ):
417
+ schema = IMySchema
418
+ additionalSchemata = (ISchemaOne, ISchemaTwo,)
419
+
420
+ # ...
421
+ ```
422
+
423
+ To render the form, do not override ` __call__() ` . Instead, either implement
424
+ the ` render() ` method, set an ` index ` attribute to a page template or
425
+ other callable, or use the ` template ` attribute of the ` <browser:page /> `
426
+ ZCML directive when registering the view.
427
+
428
+ In the template, you can use the following variables:
429
+
430
+ * ` view/w ` is a dictionary of all widgets, including those from non-default
431
+ fieldsets (by contrast, the ` widgets ` variable contains only those
432
+ widgets in the default fieldset). The keys are the field names, and the
433
+ values are widget instances. To render a widget (in display mode), you can
434
+ do ` tal:replace="structure view/w/myfield/render" /> ` .
435
+ * ` view/fieldsets ` is a dictionary of all fieldsets (not including the
436
+ default fieldset, i.e. those widgets not placed into a fieldset). They keys
437
+ are the fieldset names, and the values are the fieldset form instances,
438
+ which in turn have variables like ` widgets ` given a list of all widgets.
439
+
440
+
123
441
(classic-ui-forms-dexterity-add-edit-forms-label)=
124
442
125
443
## Dexterity add and edit forms
0 commit comments