Handling Events in Widget Components

Handling Events in Widget Components

Dynamic website content includes page elements that change as a result of visitor interaction. The purpose of an image slider, for example, is to let the visitor switch to the next or the previous image by clicking a button.

In this tutorial, we will show you how to use event handlers in widgets. Based on the Scrivito Example App, we’re going to develop a disclosure widget that requires visitors to click a button to open a panel containing some details they didn’t want to see before, e.g., the solution to a riddle, or the end of a story or movie. Similar use cases would be, for example, displaying product details or shipping costs on the same page after clicking a link.

Our DisclosureWidget will be equipped with a button for showing and hiding the information provided by an editor. Depending on its current state, this button should be labeled accordingly. Additionally, we want the information to be disclosed to have a heading and to be freely composable using widgets.

So let’s first create the widget model class to make the pieces of content (the attributes) we want to have for each actual DisclosureWidget known to Scrivito. Next, we’ll configure how the widget and which of its attributes should show up in Scrivito’s user interface. After that, we’ll take care of rendering an actual disclosure widget. This is where a click event comes into play.

Creating the widget model

In a Scrivito-based app, every widget is represented by a folder in the “src/Widgets” folder of the app, so simply create a subfolder named DisclosureWidget first, and add to it the files we are going to put together here.

Each actual DisclosureWidget has a heading and a body (we wanted it to be a widgetlist attribute), and button labels for the two states, labelHidden and labelDisclosed.

Making the content editable

Now that we have the model, let’s figure out what needs to be configured for editors to use the widget. First, an editor should be enabled to recognize the widget when wanting to select one using the widget selection dialog. For this, we’re going to provide a title, a short description, and a thumbnail attribute for it.

Second, regarding the attributes of a widget, some are predestined for being edited in place, while others should be made editable on the widget’s properties dialog. In general, all attributes that don’t require an editor to select something (e.g. a style or a color) and don’t respond to clicks (as opposed to buttons, tabs, and the like) can be conveniently edited in place, first of all string, html, and widgetlist attributes.

Thus, in the case of our DisclosureWidget, the button texts should not be made editable directly on the page because, as indicated, the click needed to focus the button for editing one of its texts would trigger the button’s click event. For this reason, we’re going to add the button texts to the widget’s properties dialog. Such details about editing attributes, as well as the widget’s appearance in the selection dialog, can be specified using Scrivito.provideEditingConfig:

This is what the above configuration effects on the widget selection and properties dialogs:

Rendering the widget

For rendering DisclosureWidgets based on the model class we provided above, we’ll pass a React component to Scrivito that implements the behavior and the appearance we want these widgets to have. The widget instance to be rendered is passed directly to the React component as a function argument.

As you can see from the code below, the component is centered around a JavaScript onClick event and its handler inside a <button> element. The button’s text and whether the panel should be rendered or not depends on the component’s isDisclosed state variable which is set to false at the beginning using React’s useState hook. This causes the value of the labelHidden attribute to be used as the button label, and the panel heading and body to not be rendered initially.

Clicking the button triggers the onClick event handler. It toggles the component’s state through a call to the set function of the isDisclosed state variable, setIsDisclosed.

If isDisclosed is true, the widget’s heading and body attributes are finally rendered using the Scrivito.ContentTag React component. The very last statement connects the DisclosureWidget component class to Scrivito using Scrivito.provideComponent to make it available in the user interface.

This is what the widget may look like after adding some content to it:

Summed up, …

Just remember to implement widgets as React components, and to connect them to Scrivito. Regarding events, changing what a widget renders as a response to, for example, a button click, can easily be accomplished using React’s useState hook. For this, provide a state variable and an event handler, and use the set function of this variable to change the component’s state and have its view updated.