Input Types v3.28
tl;dr
- Go straight to the example in the cookbook if you just want to see how a custom input type looks like.
- See the Built-in Input Types section in the menu to learn about WPCE's built-in input types.
Since WPCE v3.5, input types have no longer been a fixed entity defined by the WPCE plugin itself. Instead, additional input types could be registered from the outside.
Since then, the input type system experienced various iterations (documented here) and underwent a major overhaul in v3.28 in such a way that any input types registered from the outside can now be just as powerful as WPCE's built-in input types.
What Makes an Input Type?
An input type consists of a unique name, a Vue component for rendering it into the editor's property form and some options declaring its meta behavior.
Registering an Input Type
The registration interface is accessible through the WPCE instance's registerInputType method, so it should be used during the wpce_instance_added event:
import RadioInput from './RadioInput.vue'
document.addEventListener('wpce_instance_added', function (event) {
const editor = event.detail.instance
editor.registerInputType('radio', RadioInput, {
// additional options
})
})Rendering an Input Type
In theory, this would be a fully valid input type component:
<template>
<input v-model="model" />
</template>
<script setup>
const model = defineModel()
</script>However, most of the times when rendering the input type, some context information is needed. Such context can be received through the useInputType() composable, exposed on the global instance manager's inputTypeUtils property:
const {
/**
* Refers to the document node being edited.
*/
node,
/**
* Refers to the definition of the property which has the input type
* assigned, in particular including an `input` property with
* instructions for the input type.
*/
property,
/**
* Passing this function a callback will execute it just before
* the property form is saved. Use this to perform side effects
* that are not part of the input's value itself.
*/
onCommit,
/**
* Passing this function a callback will execute it after the
* input has been successfully validated. The callback may throw
* an error to still mark the input value as invalid.
* This is useful in situations where basic validation may be achievable
* without the component, but some more sophisticated validation
* requires the component to be rendered.
*/
onValidate,
/**
* Passing this function a callback will execute it when the
* input value has been deemed invalid. This is useful for performing
* side effects that should happen when the input is invalid.
*/
onInvalid,
} = window.wpce.inputTypeUtils.useInputType()Additional Options
These options configure the input type's behavior independently from its rendering.
layout
How the label/description and the interactive part of the input type should be arranged in a property form.
'auto' (the default) uses built-in heuristics for dispay, usually arranging it as a row.
'custom' will completely omit any label/description attached to the property and only render the input type component itself.
Type:
'row' | 'column' | 'auto' | 'custom'getDefaultValue
A callback which returns the default value for an element's property. This function is called, for example, when a new element node is created.
A property's defaultValue option takes precedence over this.
Type:
(context: {
/**
* The property definition for which the
* default value should be returned
*/
property: Wpce.Definition.Property,
/**
* Instance of the surrounding editor's `WPCE_Core` class
*/
wpce: WpceCoreClass
}) => anyvalidate
A callback which validates the value of an element's property. If an error occurs, an error message string should be thrown.
If the input type has nested properties, the callback should proactively take care and run wpce.runValidator() on them.
Type:
(
/**
* The value to validate
*/
value: Wpce.Definition.Value,
/**
* Additional context
*/
context: {
/**
* The property definition for which the
* default value should be returned
*/
property: Wpce.Definition.Property
/**
* The document node being edited
*/
node: Wpce.Document.Node
/**
* Instance of the surrounding editor's `WPCE_Core` class
*/
wpce: WpceCoreClass
},
) => boolean | Promise<boolean>checkDirty
A callback which checks if, given an old and a new version, an element's property value did change.
Type:
(
/**
* The new value to compare
*/
newValue: Wpce.Definition.Value,
/**
* The old value to compare
*/
oldValue: Wpce.Definition.Value | undefined,
/**
* Additional context
*/
context: {
/**
* The property definition for which the
* default value should be returned
*/
property: Wpce.Definition.Property
/**
* The document node being edited
*/
node: Wpce.Document.Node
/**
* Instance of the surrounding editor's `WPCE_Core` class
*/
wpce: WpceCoreClass
},
) => booleanadditionalGuids
An array of RFC 9535 JSONPath expressions which can be used to identify additional GUIDs in the input type's property value. Knowledge of these GUIDs is essential e.g. for reassigning them on node duplication.
INFO
When evaluating additional GUIDs, the JSONPath expression's $ root will be the property value itself.
Type:
string[]getNestedProperties
A callback to receive information about nested properties and how to find them from an element node property's value.
Type:
(context: {
/**
* The value to validate
*/
value: any
/**
* The input type options for the property being edited
*/
input: Wpce.Definition.InputType,
}) =>
/**
* A Map object mapping RFC 9535 JSONPath queries to
* nested property input definitions
*/
Map<string, Wpce.Definition.InputType>getFreeTextFields v3.31 β
A callback to receive information about user-controlled free text fields, e.g. for translation or content generation.
Type:
(context: {
/**
* The value which contains free text properties
*/
value: any
/**
* The property definition for which the
* free text fields should be returned
*/
property: Wpce.Definition.Property<T>
/**
* Instance of the surrounding editor's `WPCE_Core` class
*/
wpce: WpceCoreClass
}) => FreeTextField[]...with the FreeTextField type looking like this:
type FreeTextField = {
/**
* The identifier of the free text field
* Needs to be unique within the context of the property value
*/
id: string
/**
* The label of the free text field. This is only needed when a property value contains multiple
* free text fields, e.g. a link with separate label and URL fields. The label is used to
* distinguish those fields in the UI.
* For conceptually nested text fields, the label can also be an array of strings.
*/
label?: string | string[]
/**
* The context GUID of the free text field. This is used to uniquely identify the context
* in which the free text field exists. In particular, this can be set by input types which
* allow multiple instances of a property value, e.g. the repeater input.
* In that case, the context GUID is used to uniquely identify each instance, and it is also
* refreshed when the GUID of the context changes (e.g. when a node is duplicated).
* Otherwise, the GUID of the node will be used for unique field ID generation.
*/
contextGuid?: string
/**
* The JSONPath to the free text field(s) within the property value.
* It should point to a single field.
* By default, the `$` path is used, representing the entire property value.
*/
path?: string
/**
* The type of the free text field, which determines how it is edited by the user.
* Note that even fields containing HTML can be declared as 'plain' if they should
* not be edited with a visual editor, but with a code editor or similar.
* Defaults to 'plain' if not specified.
*/
type?: 'plain' | 'html'
}embeddedDocuments
An array of RFC 9535 JSONPath expressions pointing to whole document root nodes embedded in the property value.
INFO
When evaluating additional GUIDs, the JSONPath expression's $ root will be the property value itself.
Type:
string[]conditions
A semi-declarative set of conditions the current property value can be evaluated against.
Type:
Record<
string,
(
/**
* The current value to evaluate against
*/
value: Wpce.Definition.Value,
/**
* The payload passed when evaluating the condition
*/
payload: unknown,
context: {
/**
* The property definition for which the
* conditions should be evaluated
*/
property: Wpce.Definition.Property<T>
/**
* The document node being edited
*/
node: Wpce.Document.Node
/**
* Instance of the surrounding editor's `WPCE_Core` class
*/
wpce: WpceCoreClass
},
) => boolean
>