provideEditingConfig(subject, editingConfig)

Configures user-interface-related aspects of a CMS object, widget class or globally available data.

Using this API, the localization and the appearance of page and widget classes can be configured. This includes selection dialogs, details views, the initial content of pages and widgets on creation, as well as content validation checks.

Params

  • nameOrClass (String or ObjClass or WidgetClass or DataItem) – Name of the CMS object or widget class (String) based on Obj or Widget, respectively, e.g. Homepage or TextWidget.
    [New in 1.28.0]A CMS object or widget class can be passed in directly.
    [New in 1.33.0 (BETA)]An object returned by Scrivito.provideDataItem can be passed in directly as well.
    [New in 1.34.0 (BETA)]A data class returned by Scrivito.provideDataClass can be passed in directly as well.
  • editingConfig (Object) – User-interface-related configuration:
    • attributes (Object) – The localizations of the Obj or Widget class attributes. See below for details and an example.
    • description (String) – The description of the object or widget class.
    • descriptionForContent (Function) – Defines a callback that determines the description of an Obj instance. The instance concerned is passed to the function. See below for details.
    • hideInSelectionDialogs (Boolean) – Hides the object or widget class in selection dialogs from editors. The default is false.
    • initialContent (Object) – Provides automatically preset content to UI users when creating new pages or widgets. See below for details and some examples.
    • initialize (Function) – Specifies a callback to be executed whenever an Obj is created using Scrivito’s editing interface. See below for details.
      [New in 1.25.0]This callback is also executed for widgets created using the UI.
    • initializeCopy (Function) – Specifies a callback to be executed whenever an Obj is copied using the Scrivito UI. See below for details.
      [New in 1.29.0]This callback is also available for widgets that are copied using the UI.
    • properties (Array<String> or Function) – List of attributes to be shown on the “General” tab. See below for details and an example.
    • propertiesGroups (Array<Object> or Function) – List of custom tabs onto which any subset of properties can be placed. See below for details.
    • thumbnail (String) – The thumbnail for the object or widget class.
    • [New in 1.25.0]thumbnailForContent (Function) – Defines a callback that determines the thumbnail for an Obj instance. The instance concerned is passed to the function. See below for details.
    • title (String) – The title of the object or widget class.
    • titleForContent (Function) – Defines a callback that determines the title of an Obj or a Widget instance. The instance concerned is passed to the function. See below for details.
    • validations (Array<Function | Array>) – Specifies rules for content validation. See below for details and examples.

Throws

  •  ArgumentError – Passing in custom propTypes is not allowed.

Basic Examples

Provide an editing configuration for a widget class referenced by its name:

[New in 1.28.0]A CMS object or widget class can also be passed in directly:

[New in 1.29.0]Dynamic import

To increase the loading speed of the website, editing configurations can be imported dynamically, depending, for example, on the presence of an editor using the UI:

Appearance of widget and page types in selection dialogs

Using the class configuration options, title, thumbnail, and description, you can control how the Scrivito UI presents CMS object and widget classes, for example as an editor creates new pages and widgets. The following example provides a title, an icon and a description for a LandingPage class:

As an editor creates a page, the “LandingPage” type is offered nicely in the selection dialog:

Appearance of individual pages and resources in dialogs

The titleForContent and descriptionForContent functions define callbacks that determine the title of a CMS object or widget instance for display in the details view or the Content Browser. The instance concerned is passed to the function. In the following example, the headline and the description of an instance are derived from its equally named attributes.

If the headline attribute of the selected page reads “Why you should use our service”, the page will be presented in the Content Browser like shown above.

If no callback for titleForContent has been provided, the values of the contentTitle and title string attributes are used (in this order) if present. For descriptionForContent the object class name is used.

The Scrivito UI uses the text provided through descriptionForContent in places where a more verbose description of an item is appropriate.

The purpose of the thumbnailForContent callback is to determine a CMS object instance’s thumbnail for display in the Content Browser, analogously to titleForContent or descriptionForContent. The CMS object concerned is passed to the callback which must return either an instance of an image Obj or the value of a binary attribute like titleImage in the following example:

If the result of the callback is undefined, Scrivito assumes that there is no thumbnail available for the CMS object in question.

Populating the “General” tab of details views

The properties option lets you specify the list of attributes to be included on the “General” tab. If this configuration has not been provided, the tab will not be displayed for widgets, while for CMS objects the tab will only contain some pieces of system information. The order of the attribute names is acknowledged. If a title has been provided via attributes, it will be used. Otherwise, the title is derived from the attribute’s name; “backgroundColor” becomes “Background color”, for example.

Using the attributes definition, a title and a description can be provided for each attribute to specify how it should be displayed on the details view of a page or a widget. For an enum or multienum attribute, a values key can be provided to localize the available attribute values. Note that, for an attribute to show up on the “General” tab, it still needs to be included in the properties list.

Here’s an example of a LandingPage whose tags and backgroundColor attributes should be displayed on the “General” tab. The type of the backgroundColor attribute is enum, so we can also localize its values:

The above configuration includes the attributes on the “General” tab of the page properties view, using the provided titles, descriptions and values.

New in 1.26.0

Making attributes available dynamically

Attributes can depend on each other or become irrelevant if a specific option is chosen. To be able to handle this, you can specify a function for properties, which determines and returns the array of the properties to include. The SDK passes the Obj or Widget instance concerned to this function, allowing you to take account of this instance’s attribute values.

Here’s an example of a LandingPage whose backgroundImage or backgroundColor attribute is to be made available on the “General” tab, depending on the value of the pageStyle enum:

New in 1.27.0

Making attributes read-only dynamically

Instead of making attributes dynamically available, i.e. hiding them if they are irrelevant because of the current choices, you can disable them conditionally to avoid confusion.

In order disable or enable an attribute, specify a function for properties that returns the array of attributes to be displayed on the “General” tab. Each attribute can be enabled or disabled using the enabled key as an option as shown in the following example of a LandingPage whose backgroundImage or backgroundColor attribute is disabled depending on the value of pageStyle:

Customizing the in-place editing toolbar

For html attributes, the options key can be provided to customize the in-place editing toolbar of an attribute. Here’s an example of a toolbar that doesn’t support headings in text widgets:

VIEW THE FULL LIST OF AVAILABLE TOOLBAR BUTTONS
  • blockquote
  • bold¹
  • bulletList
  • clean
  • code
  • codeBlock

  • header1
  • header2
  • header3
  • header4
  • header5
  • header6
  • indent¹
  • italic¹

  • link
  • mark
  • orderedList
  • outdent
  • strikethrough¹
  • subscript
  • superscript
  • underline

¹ Some toolbar actions may create different markup, depending on the Scrivito version or the editor’s browser. For example, the bold action may create strong or b tags, strikethrough may result in s or strike.

The default buttons are:

New in 1.32.0

Limiting HTML tags

You can control the markup generated when the contents of html attributes is edited in place. Setting the allowedTags option to a list of tag names causes all other HTML tags to be removed from the attribute value. As a default, Scrivito allows using all tags typically present in basic HTML.

Please remember to set the toolbar option accordingly. If the toolbar includes buttons for disallowed tags, the resulting behavior is undefined.

New in 1.25.0

Disabling HTML markup editing

With attributes of the html type, you can hide the tab for viewing or editing their markup from the page or widget properties view by setting the showHtmlSource option to false. By default, showHtmlSource is true.

New in 1.35.0

Enabling multi-line editing for string attributes

You can enable multi-line editing for string attributes in the attribute properties. Setting the multiLine option to true will display a textarea instead of a simple input for the attribute.

However, note that line breaks that are added via the textarea do not necessarily automatically appear in the page content. If they don’t, consider applying CSS styles for white-space to your element using values such as pre, pre-wrap, pre-line or break-spaces.

Adding custom tabs to properties views

The propertiesGroups option lets you provide a list of custom tabs containing attribute properties. Each group should have a title key (the title of the resulting tab) and a properties key specifying the names of the attributes to be displayed on the tab. The order of the attribute names is acknowledged.

[New in 1.26.0]Furthermore, a key as a unique group identifier can and should be specified to speed up rendering (like keys in React do).

As with the properties option, if an attribute’s title has been specified in the attributes definition, it will be used in propertiesGroups. Otherwise, the title is derived from the attribute’s name; “backgroundColor” becomes “Background color”, for example.

In the following example, we want the facebookUrl and twitterUrl attributes to be made available on a dedicated “Social media” tab:

[New in 1.26.0]Like with properties, propertiesGroups can be provided as a callback function for determining the groups dynamically based on the passed-in Obj or Widget instance. Each group in the returned array must have a unique key, otherwise an error is thrown.

In the example below, the “Facebook” group is only displayed if a facebookUrl has been specified.

[New in 1.27.0]Instead of hiding groups, you can disable them, like with properties. In the example below, the “Facebook” group is disabled if no facebookUrl has been specified:

Using Scrivito extensions in properties views

A Scrivito extension is a component your application provides for the purpose of integrating it into the Scrivito UI. The propertiesGroups option not only lets you specify a list of custom tabs populated with attribute properties, but alternatively lets you define custom tabs on which Scrivito extensions are used (you cannot have both).

There are two approaches to setting up an extension for a property group: You can provide the component directly, or reference it by its name.

New in 1.27.0

Providing the component directly

This approach is the more flexible and convenient one. Directly specifying a functional React component for the component key allows you to pass any number of props to it and use all of React’s functionality. Here’s an example of such a component for use on a “Social media” tab in a properties view:

In the editing configuration of the model class concerned, a corresponding property group can then be set up to use the above component:

[New in 1.27.0]Properties groups can be enabled or disabled by specifying the enabled key in their definition.

Referencing a component by its name

The second approach to integrating an extension is to provide a property group that references the component to use by its name, like so:

The component to be rendered must be registered using Scrivito.registerComponent. To the component, either a widget, page or obj prop is passed, depending on whether it is meant to be displayed in the details view of a widget, a page or, respectively, a CMS object not representing a page but, for example, an image.

Here’s an example of a component that renders two string attributes on the “Social media” tab defined above as a properties group:

For a more extensive example, take a look at our tutorial on Customizing page and widget property editing.

Content validation for extensions

When using extensions in combination with content validation and want custom tabs with invalid content to be highlighted, or for having changed content indicated, specify the list of attributes concerned using the properties key:

Providing initial content

The initialContent option lets you specify the default initial content when creating new pages or widgets via the user interface.

Each key inside initialContent refers to an attribute in the Obj or Widget. Each value is either a value that fits the attribute’s type (compare Obj.create, for example), or a callback that returns such a value. If a callback is given, it is executed each time an Obj or Widget is initialized, and the returned value is used.

The provided initial content will be used:

  • Whenever a new Widget or Obj is created using the UI (regardless of how this is done: menus, buttons, Content Browser – all apply the initialContent).
  • Whenever a new Widget or Obj is created programmatically by the customer’s app using the Obj.create or new Widget API.

Initial content will not be applied if a new Widget or Obj is created by copying (or duplicating) an existing one.

When creating Objs or Widgets via the API, initialContent values are only given to attributes whose values aren’t set by the API call. In other words: If a Widget or Obj is created with an explicitly given value, the corresponding initialContent value is ignored.

Initial content may be provided for any custom attribute but not for system attributes.

Initializing CMS objects and widgets

For each Obj and Widget class, the application can provide a callback that is executed immediately after an instance of it has been created and the initial content has been assigned to it. The new Obj or Widget is passed as the only argument to the callback. It can be specified in the editing configuration and can update the instance passed to it.

In the following example, the callback ensures that the author of a blog post is properly set, depending on the path of the post in question:

If the callback needs to load data, it can do so by using Scrivito.load. This allows it to be asynchronous. In the following example, the callback ensures that the title image of a blog post is properly set:

The callback is triggered by all actions in the UI that create an Obj or a Widget, for example, whenever

The callback is not executed, however, when Obj#create is called. If the SDK’s API is used to create an Obj, its attributes can be passed directly to Obj#create, or the Obj can be updated afterwards:

The callback is also not executed if a CMS object is copied or duplicated using the UI. For initializing such copies, the initializeCopy callback is available.

Initializing copied CMS objects and widgets

For every Obj class, the application can provide a callback that is executed after creating instances of them by means of copying. The only argument passed to this callback is the Obj that was created. The callback can be specified in the editing configuration and may update the created instance.
[New in 1.29.0]The callback can also be provided for Widget classes.

In the following example, the callback ensures that the author of a blog post is properly set:

If the callback needs to load data, it can do so by using Scrivito.load. This allows it to be fully asynchronous:

In the example below, the callback ensures that the text in a headline widget is properly aligned.

The callback is executed along with any copying action performed using the editing interface, for example, whenever

  • an editor duplicates a page using the main menu at the top right, or, respectively, duplicates a widget using its context menu,
  • a page is pasted using the menu of an automatic navigation (see also Scrivito.ChildListTag),
  • a page including its subpages is pasted,
  • a widget is dragged from the widget library sidebar and dropped onto a page,
  • a widget is pasted using a widget’s context menu.

Since duplicating or copying and pasting a page also copies the widgets on it, the initializeCopy function defined for them is executed as well.

When duplicating or copying and pasting a page with subpages, the callback is also executed for the direct and indirect ancestors of the page as well as for the widgets on these pages including those nested within them. The order in which the callbacks are executed for the CMS objects and widgets involved is not specified.

The callback is not executed if Obj#copy is called. When using the API to copy an Obj, update the result of Obj#copy instead:

Defining validations

With Scrivito-based applications, you can have the UI ensure that CMS objects or widgets (of a specific type) and their custom attributes contain valid content, based on the application’s business logic.

By default, validation results are considered errors preventing the working copy from being published. The Scrivito UI displays the notification messages you provide and assists editors with locating the rejected pieces of content. Nevertheless, it is advisable to keep validations simple and the messages to be displayed in case of errors as clear and helpful as possible.

The severity of a validation result can be changed so that it is not treated as an error but as a warning or an informational message (see below for an example). Unlike errors, the latter two severity levels doesn’t prevent the working copy from being published. In the UI, the severity level of a validation notification is indicated using colors and icons.

The validation logic can be provided in the editing configuration under the validations key. The validation configuration is basically an array containing the validation definitions.

Since a single validation can either be focused on the state of an entire model (an Obj or a Widget), or be only relevant in the scope of a single custom attribute (e.g. title), we differentiate between class-based validations (validations for the content model as a whole) and attribute validations (validations for an attribute value).

Validation callbacks

Validations can be provided as callbacks that are executed either for CMS object or widget class instances as a whole, or for an instance attribute. For flawed content, a callback must return a string or an array of strings representing validation message(s). If the content is considered valid, it must return a falsy value, i.e. undefined, null, or "".

  • Like render methods in React, validation callbacks should be light-weight, idempotent and free from side effects. Expect them to be executed frequently and at times that cannot be predicted.

    Validation callbacks are meant to be applied to a specific CMS object or widget. They may access other CMS objects or perform searches as well. However, this must be implemented with care to neither run into logic errors nor affect the performance of the application or the user interface.

Class-based validation using callbacks

For class-based validation, the callback can be placed anywhere in the validations array. It receives the current content model (an Obj or a Widget):

As mentioned above, it is possible to change the severity level of a validation. This can be achieved by returning not just the message but an object with two keys, message and severity, the latter set to warning or info (with error being the default):

The code inside a validation callback can access models and their attributes without being wrapped in Scrivito.load.

Attribute validation using callbacks

With attribute validation, the callback receives the current attribute value as well as an options object with the following keys:

  • obj, if the subject of validation is an Obj.
  • widget, if the subject of validation is a Widget.
  • content also provides the subject of validation (for convenience).
  • name – the name of the attribute.

Attribute validations can be provided for any custom attribute. In addition, validations can be defined for these system attributes:

  • [New in 1.31.0]_permalink
  • [New in 1.32.0]_language

An attribute validation callback is specified as an array, with the first element being the attribute name, followed by one or several validation callbacks:

Attribute validation using constraints

For validating an attribute based on higher-level constraints, a constraint validation callback can be configured.

The structure of the constraints depends solely on the DSL of the library used. With Validate.js, it looks like this:

By default, the result of a validation using constraints is considered to be an error preventing the working copy in question from being published. However, it is also possible to change the severity. This is done by putting the constraints inside an array, with the first element being a special configuration object and the second the object respresenting the constraints. The configuration object can have a single key severity with allowed values error, warning and info:

Extended example