-
Notifications
You must be signed in to change notification settings - Fork 27
Editing Components with Forms
The main way people interact with components is through forms. These allow you to edit single fields, groups of fields, and component settings in a consistent and manageable way. The simplest possible form is a single field in the schema:
title:
_has: text
And a corresponding data-editable
attribute in the template:
<div data-editable="title">{{ title }}</div>
When someone clicks on the title, a form will open with a single text input, allowing them to edit it.
Each field in a form is composed of "behaviors": Small, self-contained templates with styles and logic that can be combined together. Kiln has many built-in behaviors, and custom behaviors can be added through the API.
To add behaviors to a field, list them in the order they should display in the UI:
title:
_has:
- label
- required # add 'Required' after the label
-
fn: description
value: A concise description of this field
-
fn: wysiwyg
type: single-line
buttons:
- bold
- italic
As you can see, Kiln provides some syntactical sugar to make writing behaviors easier. They can be specified as strings, objects, or arrays of objects, depending on how complex your field is.
# if you have a single behavior with no arguments, you can simply use a string
hasOneBehaviorWithNoArguments:
_has: text
# if you have a single behavior but it has arguments, use an object
hasOneBehaviorWithArguments:
_has:
fn: text # fn points to the behavior, e.g. behaviors/text.js
required: true # native html form validation
# if you have multiple behaviors, use an array
hasMultipleBehaviors:
_has:
- label
- text
# you can mix and match strings (behaviors without arguments) and objects (behaviors with arguments) in your arrays
hasMultipleBehaviorsWithArguments:
_has:
- label
- required
-
fn: description
value: Write stuff here
-
fn: text
type: url
By default, field labels (in forms, validation messages, and other places) will use the name of the field. You may specify a different label by adding _label
to a field:
title:
_label: Post Title
_has:
- label
- text
The label
behavior (and any other place where the field name would display) will now use "Post Title" instead of simply "Title".
There are three ways Kiln displays forms, governed by the _display
property: inline
, overlay
, and settings
. Besides allowing different functionality, certain displays are better for editing certain types of content.
Inline means that the form will replace the content inline. It is best when there's a 1:1
match between how your content looks and how it's edited. Some examples:
- clicking into a paragraph should display a
wysiwyg
text editor inline - clicking into a header should allow you to edit that header (a single
text
field) in place - clicking on an image should allow you to change that image
text:
_display: inline
_has:
fn: wysiwyg
type: multi-component
styled: false
buttons:
- bold
- italic
- strike
- link
-
phrase:
class: clay-annotated
button: A¹
Overlay is the default way forms display, and means they'll open up in an overlay pane when clicked. It's best when there's a 1:many
match between how your content looks and how it's edited. Some examples:
- an article headline displays a single line of text, but when editing you want to specify long, short, social, and seo headlines
- links look like a single line of text, but when editing need a url and title
date:
_label: Published Date
_has:
- label
-
fn: description
value: The date and time an article was <b>first</b> published.
-
fn: text
type: datetime-local
Settings is a special kind of overlay form that's best when there's a many:many
match between how your content looks and how it's edited. Some examples:
- a social share component allows you to enable or disable a large number of social media services
- an article has metadata that's never displayed, but is used to generate feeds and gets sent to analytics
- a feed component specifies the exact elasticsearch query it uses to populate items
enabled:
_label: Enabled Services
_display: settings
_has:
- label
-
fn: description
value: Choose which services are displayed.
-
fn: checkbox-group
options:
-
name: Facebook
value: facebook
-
name: Twitter
value: twitter
-
name: LinkedIn
value: linkedin
-
name: Google Plus
value: gplus
-
name: Pinterest
value: pinterest
-
name: Tumblr
value: tumblr
-
name: Email
value: email
-
name: Print
value: print
twitterHandle:
_label: Twitter Handle
_display: settings
_has:
- label
-
fn: description
value: Twitter handle to include in tweet use when sharing
- text
While settings forms look similar to overlay forms, they don't correspond to a data-editable
attribute that people can click. Instead, a component with a settings form will show a gear icon in the component selector, allowing the end user to access it.
Placeholders, governed by the _placeholder
property, prompt people to click into forms. If a placeholder is defined, people will see it in edit mode when the field is empty.
title:
_placeholder:
text: Headline # text for the placeholder label
height: 30 # height in pixels
required: true # should the placeholder display 'Required'?
_has: text
The placeholder will be a child of the element with the relevant data-editable
attribute:
<div data-editable="title">{{ title }}</div>
If you want to display a placeholder for some field, but don't want to allow users to click into it, use the data-placeholder
attribute. This is useful for situations where a component might only have settings (like an ad), or where you want the placeholder to display some kind of data (like a video ID).
<span data-placeholder="settings">Do not click</span>
You can specify permanent: true
to always display the placeholder (in edit mode). This will give the placeholder a more subtle styling and prevent it from disappearing when data is added.
adName:
_placeholder:
text: Ad
height: 100
permanent: true
Placeholders can display the value of a field, which is useful for components not visible during edit mode, e.g. third-party embeds. The syntax for displaying a value in the placeholder text is ${fieldName}
, which is similar to JavaScript template literals. Note that permanent: true
must be set.
adSizes:
_label: Ad Sizes
_display: settings
_placeholder:
text: Ad (${adSizes})
height: 100
permanent: true
When deciding how to add placeholders, keep these things in mind:
- Placeholder height should reflect how the component will look when data is added to the field. A single line of text will be short, while a component list will probably be taller.
- If you specify a placeholder height below 50px, it will use more compact single line styling.
- Placeholders are specified in the component schema, so all instances of that component will have the same placeholder text, height, and logic.
- That being said, you can override the height on a per-instance basis by setting different
height
styles on the component element itself. - Placeholders will display "this page" or "multiple pages" based on where the component lives. The latter denotes a component living inside a layout.
In most inline forms, you'll want to edit a single field (e.g. when editing a paragraph). In most overlay and settings forms, though, you'll want multiple fields. This is where groups come in.
Groups can be used to open forms with multiple fields in both inline and overlay forms, or when you want to guarantee the order of fields in your component settings form.
In the root of your schema, add a _groups
object that contains a fields
array.
title:
_has: text
url:
_has: text
_groups:
myGroup:
fields:
- title
- url
If a data-editable
element in your template points to that group, clicking it will open a form with all of that group's fields, in order.
<div data-editable="myGroup"></div>
You can add _label
, _display
, and _placeholder
properties to groups, the same way you would fields. Groups can be displayed inline
as well as overlay
.
_groups:
link:
fields:
- title
- url
_label: Link
_display: inline
When opening a form for a group, the _display
and _placeholder
properties of the individual fields are ignored. This means that you don't have to specify those properties in your fields if they're only used in groups.
If you add a _placeholder
to a group, you must either make it permanent (with permanent: true
) or specify what fields it should check (with ifEmpty: fieldName
). It will display the placeholder when that field is empty.
_groups:
link:
fields:
- title
- url
_label: Link
_display: inline
_placeholder:
text: Link
ifEmpty: title
Placeholders in groups may check multiple fields with a logical operator. This is handy for components with editable links, as you'll usually want to display a placeholder when either the url or the link text are empty. Operators are case-insensitive, and you can use AND
, OR
, or XOR
.
_groups:
link:
fields:
- title
- url
_label: Link
_display: inline
_placeholder:
text: Link
ifEmpty: title OR url
Please note that when comparing more than two fields, you cannot use XOR (as it's logically impossible to XOR more than two boolean values). You must also use the same comparator between each field, rather than mixing and matching them.
By default, Kiln will look through your fields to generate the component settings form. It will add any field with _display: settings
to the form, but (because schemas are objects) there's no guarantee that the fields' order in the schema will be their order in the form.
If you want to guarantee the field order in your component settings form, you can create the settings
group manually. This will override the default logic, so remember to add all of the fields you want to have in your settings form.
_groups:
settings:
fields:
- title
- url
You don't need to specify _label
(the form will be called "[Component Name] Settings"), _display
, or _placeholder
for the settings group. You also don't need to specify _display: settings
inside the individual fields.
Overlay and settings forms may also use tabbed sections. Specify them in the fields property of your group by wrapping the section name in parenthesis (similar to how you specify site-specific components in a component list)
_groups:
settings:
fields:
- alt
- imageLink
- creditOverride
- slideshowJSONPath (Slideshow)
- slideshowButtonText (Slideshow)
- slideshowType (Slideshow)
- sass (Custom Styles)
If you specify sections for some fields but leave the other fields blank, they'll be added to a "General" section. Fields and sections will appear in the form in the order they've been listed.