Letting Editors Create Web Interfaces Utilizing Data

Letting Editors Create Web Interfaces Utilizing Data

With Scrivito, building interfaces that utilize and nicely present internal or external data of any kind, be it personal data in a portal, or product data in an online shop, has long been exclusively in the hands of app developers. This has changed recently when Scrivito SDK APIs were released for working with such data directly in the editing interface. Providing the foundation for this is of course still left to developers, but has become a lot easier.

This guide wants to give you an insight into the clockwork behind accessing and presenting internal or external data. The datalocator attribute type on one side and data classes on the other form the basis on which editors can freely compose attractive web pages that embed data from any kind of source a JavaScript-based app can use. We will develop a universal “DataListWidget” for the Scrivito Example App here and connect it to a small handmade internal employee database via a data class to illustrate and convey how the cogs mesh together.

We’ll jump right in, assuming that you’re familiar with Scrivito’s data structures, and may even have developed a widget already.

The “datalocator” attribute type

The datalocator attribute type enables editors to add data from internal or external sources as content to webpages. Internal data typically originates from CMS objects of one of the types available, representing, for example, job offers, events, products, etc. For working with external data, a data class including a callback at least for retrieving the data, and, depending on the use case, also callbacks for creating, updating, and deleting individual pieces of this data need to be provided.

If a widget has an attribute of the datalocator type, Scrivito’s editing interface allows editors to select an object type or a data class as the data source to be used. Furthermore, filters based on the properties of the source can be specified, as well as the ordering and maximum size of the result set. The widget is then rendered based on this result set.

Creating a DataListWidget

A datalocator attribute is usually part of a widget that also renders it. A rather basic widget class definition that includes such an attribute would look like this “DataListWidget”.

Next to the data attribute, the widget has a widgetlist attribute named content. We will use it to render the employee data coming in from the datalocator. For the widget to properly advertise itself, e.g., in the widget selection dialog or sidebar, give it a title (and maybe also a description) via an editing configuration:

To render instances of the “DataListWidget”, the widget’s component below first fetches the content of the data attribute using get, and, using the useDataLocator hook, makes this content a DataScope, an array of DataItems. This array is then iterated to output as many Scrivito.ContentTag components for the content widget list as the data scope contains items:

The magic here lies in the dataContext prop receiving an individual DataItem, including all its attributes, each time Scrivito.ContentTag is rendered. If an editor now adds a content widget, e.g. a text widget, to any of the content widgetlists, their respective data context serves as the source from which the content widgets can retrieve the data item’s attribute values, for example, to fill in placeholders.

Making external data available through a data class

To exemplify how internal or external data can be made available to your Scrivito-based web application so that editors can build webpages displaying it, we will use an app-internal “database”, a JSON array containing a few employee records. In a real-life use case, you would of course fetch such data via the RESTful API endpoints your data source offers.

But first, let’s prepare our app for such data and the data class by providing the “infrastructure” for all this.

Providing the infrastructure

In your code base, first create the “src/Data/Employee” directory path, analogously to “src/Objects/…” and “src/Widgets/…”. Then, make sure that the files defining classes and editing configurations are imported when the app is launched.

Show the files to adjust, following the example App conventions

Next, in the app’s main index.js file, import the files in the “Data” subdirectory as well as the “editingConfigs.js” file:

Finally, also import “Data” and “editingConfigs.js” as extensions:

Adding the data class and editing configuration definitions

Now that everything is prepared, we can elaborate on and finally define our Employee data class. Its purpose is to facilitate access to the employee data, and pass it to the app via the datalocator attribute of our “DataListWidget”. In other words, a data class serves the Scrivito SDK as an interface to the data source. Whenever a component of your app makes use of a datalocator attribute, the SDK relies on the callback routines implemented in the corresponding data class to fetch (get), list (index), create, update, or delete the pieces of data concerned.

Our Employee data class doesn’t implement all of these callbacks, but only get and index for retrieving individual records, and, respectively, for listing and filtering the employee data as a whole. The file also accommodates the employee “database”:

The above call to Scrivito.provideDataClass yields our Employee data class. Its get callback returns the record referenced by the id passed in.

The index callback first filters the database by the criteria specified for the datalocator attribute. Usually, you would accomplish this by sending a corresponding request to your remote service. Finally, the index callback returns an object with an array containing the IDs of the records that are left after filtering.

Providing placeholders

To enable editors to insert the values of the properties contained in the database records into the page content, let’s provide the relevant properties as placeholders by creating an editing configuration for the Employee data class:

An editor who wants to add an employee’s name, email address or department to their content (in a “DataListWidget” instance) can now mark a piece of text, select “Variable” from the toolbar that appears, and then pick any of the three variable names.

Try it out!

To test our new “DataListWidget” in combination with the employee database, we’ve added a page to the Example App, and placed two of these widgets on it. The first one filters the dept property for “Marketing” as shown on the screenshot above, the second one for “Sales”. Both contain three text widgets with placeholders for the employee data.

Voilà!

Final notes

A DataScope like the one we used in our widget component above has a create method for creating DataItems. To update or delete a DataItem, its update and destroy methods are available. Using these methods requires the DataClass to be equipped with the corresponding callbacks, of course.

If you want to make data globally accessible as a DataItem, Scrivito.provideDataItem lets you do this.