Skip to content

Editing Components with Forms

Nelson Pecora edited this page Sep 15, 2017 · 9 revisions

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.

Behaviors

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

Field Label

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".

Display

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: 


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


Settings vs Overlay

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

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>

Permanent Placeholders

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

Placeholder Considerations

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.

Groups

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.

Creating a Group

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.

Group Placeholders

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.

Settings Group

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.

Tabbed Form Sections

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.