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. As the icing on top, we will then add an employee details page and link to it from within our data list widget.

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

Let’s 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 a text widget with placeholders for the employee data.

Voilà!

Adding an employee details page

In connection with a data list, a details page serves to display or edit some or all of the properties of an individual list item. Providing such a page makes sense if the items feature more properties than those you want to have rendered in the list, which definitely doesn’t apply to our employee data with only three properties. But to illustrate how such a page can be set up, we’ll provide one here for an individual employee.

Basically, a details page can be regarded and set up as a regular page equipped with a datalocator attribute named data. Scrivito identifies a details page only by this combination of the data attribute name and datalocator type, found in the object class concerned, and then, in the editing interface, automatically adds a “Data” tab to the page instances of this class. You can now specify the data class of the items the details page is about, and place a link pointing to this page into the corresponding data list widget. If you then follow this link, the details page lets you use the properties of those items as placeholders. Furthermore, when developing a page component, e.g., a widget, you can access the current item through Scrivito.useDataItem.

We’ve created a details page class for our employee data simply by copying the standard “Page” class, its component and editing configuration, and naming the files “DetailsPage*”. Then, we’ve adapted the names and titles, cleaned up the code a little, and added the data attribute:

Based on the above generic “DetailsPage” object class, you can now create an actual and specialized employee details page. To do this, open its page properties, and, on the “Data” tab, select “Employee” as the details data source.

Next, return to the page containing the employee data list, and link anything in it to the new details page. We’ve chosen the employee’s name, i.e. a variable, but any link to the details page in any widget inside the data list widget will do.

Finally, navigate to the details page using the link you’ve created, add a text or headline widget to the page, and start inserting employee variables as needed!

         

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