-
Notifications
You must be signed in to change notification settings - Fork 27
v0.x → v3.x Migration Guide
Kiln 3.0 is here! To take full advantage of it, though, you'll need to make a few changes to your setups.
First things first, make sure your clay-kiln
component is in a non-editable component list in your layouts. This prevents Kiln from trying to edit itself or reload its preloaded data. The convention we're using at NY Mag is to put Kiln (and any Kiln plugins) in a kiln-internals
component list. The schema looks like this:
kilnInternals:
_componentList:
internals: true
include:
- clay-kiln
- clay-space-edit
And the corresponding template looks like this (note the separate, editable foot
component list, where we're putting invisible components):
<div class="foot" data-editable="foot">{{ > component-list foot }}</div>
<div class="kiln-internals">{{ > component-list kilnInternals }}</div>
While Kiln v1.0 still supports server.js
and server-side rendering, you should convert all of your components to model.js
and handlebars templates (docs here) to allow them to render client-side instantly. This also enables cross-component updating for those components.
NOTE: model.save()
and model.render()
have timeouts to preserve the fast editing experience. There are a number of strategies to deal with slow saves (TK link to wiki page)
In Kiln v1.0, the schemae and data for all components on the page will be preloaded when the page loads. This allows quick editing of those components without having to fetch extra data from the server. In addition, the models and (handlebars) templates of all installed components will be preloaded. Kiln's application code is not inlined, so it'll load in parallel with the html page and will be browser cached for speed.
Kiln v1.0 allows for cross-component updating, tabbed sections in forms, behavior ordering, multiple buttons (like magic-button
and lock
) on text inputs, and much more consistent wysiwyg editing using Quill. It also introduces a number of new behaviors and breaking changes to current behaviors.
Components can affect other components on the page by publishing and subscribing to properties (such as title
, description
, ledeImage
, etc). This allows many-to-many communication in Kiln, as multiple components can publish or subscribe to the same property, and components can publish or subscribe to multiple different properties. There are no restrictions on pubsub property names, so be sure to avoid unintended collisions!
Components that use model.js
may publish changes that they would like to propagate to other components on the page. To do so, add a _publish
property to the specified field with the name of the property it should publish to.
pageTitle:
_publish: pageTitle
_has: text
Properties will be published after a component's model.save()
function is called, allowing that component to perform logic before propagating its data. It may be useful to add extra fields to a component's schema which are only populated by model.js
, if the data for them is generated from multiple user-editable fields.
Components that want to subscribe to properties should have a _subscribe
property on the field(s) they want to update, with the name of the property it should subscribe to.
twitterTitle:
_subscribe: pageTitle
_has: text
Subscribed properties will trigger a component to save, thus allowing the subscribed component's model.save()
function to do logic on the incoming data before it's sent to the server. If multiple properties are subscribed to, Kiln will wait until all of the data has been published before triggering the save.
Kiln intelligently prevents a component from saving more than once during pubsub, so you may safely create circular pubsub logic. For example, a tags
component may update an article
's primaryTag
field, and the article may also allow editing of that field (and propagating those changes back to tags
).
As cross-component updating is a feature of Kiln, it only works client-side. For third-party microservices or manual API calls, please make use of cascading PUTs to affect multiple components.
Forms that aren't inline (e.g. overlay
and settings
) may now have tabbed sections. Specify the sections 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.
One very prominent change is that behaviors are now placed in specific parts of a field (before
the input, in the main
input, and after
the input). Behaviors in the same slot (e.g. label
and description
) must be listed in order in a field's schema.
In Kiln v0.x, you might have a field that looks like this:
url:
_label: Image URL
_has:
-
fn: text # old text input had to be at the beginning of the list
type: url
- required # other behaviors added randomly
-
fn: description
value: Paste the URL to your image or drag the image from Mediaplay into this field.
- label
In Kiln v1.0, you must add them in order. Note that behaviors which go into different slots (e.g. label
and text
) can be in any order (i.e. you can still put text
first in the list), but it's good practice to put them in the order that you expect them to appear in the Kiln UI.
url:
_label: Image URL
_has:
- label
- required
-
fn: description
value: Paste the URL to your image or drag the image from Mediaplay into this field.
-
fn: text
type: url
The new reveal
behavior conditionally hides and shows a field based on the value of another field. (more info)
The conditional-required
behavior acts like the required
behavior, but sets a field required or not based on the value of another field. (more info)
For Kiln v1.0, all current behaviors have been rewritten as Vue components. Their full documentation is automatically generated, but here is a list of notable changes:
-
autocomplete
andsimple-list-primary
are now part ofsimple-list
, rather than separate behaviors -
magic-button
allows astore
argument, which will pull component data from the client-side store rather than doing api calls to the server -
magic-button
preserves formatting when grabbing rich text fromwysiwyg
fields -
lock
can now be toggled, allowing re-locking of unlocked fields (they will always be locked when a form is opened, but this gives a nice appfeel for the end user) -
_placeholder
height is now a number, not a string with units -
_placeholder
text cannot display html, only plaintext
The wysiwyg
behavior has been rewritten from the ground up to use Quill rather than medium-editor. This allows for more formatting options, better paste handling, and ironclad html sanitization due to being backed by a real document format. Full documentation of the new wysiwyg
behavior is available here. Notable changes include:
-
enableKeyboardExtras
is now separated into thetype
andpseudoBullet
arguments -
type: single-line
is the affordances you had in Kiln v0.x withenableKeyboardExtras: false
-
type: multi-component
is similar toenableKeyboardExtras: true
(paste rules are parsed for multi-component paste, etc) -
type: multi-line
is new functionality enabling multiple paragraphs in a single wysiwyg field (useful for components like blockquotes) - newlines are now created with enter rather than shift + enter
- new paragraphs are now created by pressing enter twice
-
multi-component
wysiwyg fields allow keyboard arrow navigation between component instances - buttons and formats have extended functionality, including
phrase
(creates a<span>
with a specified class)
Phrases are spans that may have any whitelisted (see list) class. Specify them by passing in a string or object to the buttons
argument.
fn: wysiwyg
buttons:
- bold
- italic
- phrase # no class
-
phrase:
class: clay-annotated # custom (whitelisted) class
button: A¹ # custom button text
Whereas Kiln v0.x had a hodgepodge of events and globally-exposed services, Kiln v1.0 has proper API support for custom behaviors, panes, validators, handlebars helpers, and plugins (things that need to subscribe to changes in the client-side store
).
Custom behaviors should be added to window.kiln.behaviors['your-behavior-name']
. They should be a .vue
file that exports a component, and they can overwrite built-in behaviors if desired.
Custom panes should be added to window.kiln.panes['your-pane-name']
. They should be a .vue
file that exports a component. Panes can be triggered by calling openPane
:
store.dispatch('openPane', {
title: 'Title of Your Pane',
position: 'right', // 'left' is the default
size: 'large', // 'medium' is the default
content: {
component: 'your-pane-name',
args: {
// any arguments you want to pass into your pane
}
}
});
In Kiln v0.x, validators received a hodgepodge of data and had to parse the DOM for a lot of their logic. In Kiln v1.0, validators now receive the client-side store's state
object, with data for components
, schema
, page
, etc. Validators may still access the DOM, but the vast majority of data validation should be done by simply mapping/reducing over the state
.
Custom validators should be added to window.kiln.validators['your-validator-name']
and may overwrite built-in validators. Validators should export an object with label
, description
, type
(error
or warning
), and validate
(a function that receives state
) properties.
If a validator passes, it should return either undefined or an empty array. For errors, return an array of error objects.
[{
uri: 'domain.com/components/foo', // uri of the component
field: 'someField', // optional field to link directly to in the validation message
location: 'Component Name » Field', // human-readable error message
preview: '...tk foo...' // optional preview of the bad data, or additional information about the error
}]
NOTE: Validators may return promises!
Kiln v1.0 pulls in the nymag-handlebars library, but you may add custom handlebars helpers to window.kiln.helpers['your-helper-name']
. You may overwrite built-in helpers, but that is not recommended (as it makes troubleshooting templates issues a lot more difficult, and the helper namespace is effectively infinite).
If you need to listen to mutations on the client-side store, you should create a plugin and add it to window.kiln.plugins['your-plugin-name']
. These are passed directly into the vuex store.