cliveportman/code

Form inputs for Craft CMS control panel plugin entry form templating

I haven't found any definitive documentation on creating form fields within Craft CMS's control panel, but dotted around Stack Exchange there have been enough examples to figure out the concepts. They are all some variation on the examples below but have different variables required. Find out more about the variables by looking at the individual fieldtype files within craft/app/fieldtypes/ and seeing what variables are used within the getInputHtml() and defineSettings() functions.

For all of these you'll need to include this:

{% import "_includes/forms" as forms %}

Note the use of default for situations when a value doesn't exist. It means you use the same form for new-entry forms and edit-entry forms. 

Lightswitch fields are surprisingly simple with the on being a boolean:

{{ forms.lightswitch( {
    id: 'paymentstatus',
    name: 'fields[paid]',
    on : invoice.paid | default,
} ) }}

Text fields:

{{ forms.text( {
    id: 'invoicetitle',
    name: 'title',
    value : invoice.title | default,
    placeholder : 'Invoice number',
    size: 'notfullwidth' // will be fullwidth if not set
 } ) }}

Textarea fields:

{{ forms.textarea( {
    id: 'address',
    name: 'field[address]',
    value : school.address | default,
    placeholder : 'e.g. 123 Main Road, Norwich, Norfolk',
    multiline : TRUE
 } ) }}

Assets fields are a bit more complicated. They use something called elementSelect which is also used with entries and other relations. I'm not sure what the sourceElementId is but it doesn't seem to be needed. The elements variable is used to pre-populate with existing assets on an Edit Entry form and the sources are the folders you want to allow:

{{ forms.elementSelect({
    id: 'invoicePdf',
    name: 'fields[invoicePdf]',
    elementType: craft.elements.getElementType("Asset"),
    elements: invoice.invoicePdf | default,
    criteria: {"kind":[],"localeEnabled":null,"locale":"en_gb"},
    sourceElementId: 1,
    jsClass: 'Craft.AssetSelectInput',
    addButtonLabel: 'Upload invoice',
    limit: 1,
    sources: ['folder:1']
}) }}

User fields work the same way as Asset fields. I've added the sources here, restricting the users to a single user group:

{{ forms.elementSelect({
    id: 'schoolteacher',
    name: 'fields[schoolTeacher]',
    elementType: craft.elements.getElementType("User"),
    elements: school.schoolTeacher | default,
    criteria: {"kind":[],"localeEnabled":null,"locale":"en_gb"},
    jsClass: 'Craft.AssetSelectInput',
    addButtonLabel: 'Select user',
    limit: 1,
    sources: ['group:2']
}) }}

Date fields are, seriously, as easy as:

{{ forms.date({
    id: 'fields-invoiceDate',
    name: 'fields[invoiceDate]',
    value: invoice.invoiceDate | default
 }) }}

Combined date and time fields require two separate inputs even if belonging to the same field. The id attributes will be appended with either -date or -time:

{{ forms.date({
    id: 'visitDate',
    name: 'fields[visitDate]',
    value: visit.visitDate | default
}) }}
{{ forms.time({
    id: 'visitDate',
    name: 'fields[visitDate]',
    value: visit.visitDate | default
}) }}

Checkbox fields are something like this but I don't think this example was saving on an Edit Entry form (so I changed it for a Lightswitch field which looked better anyway):

{{ forms.checkbox( {
    id: 'paymentstatus',
    name: 'fields[paid][]',
    value : 'paid',
    checked: 'checked',
    label: 'Yes'
} ) }}