Test Enterprise-Class Web CMS Scrivito Free for 30 Days
Test Scrivito Free for 30 Days

Introduction to Creating and Rendering Pages and Widgets

Introduction to Creating and Rendering Pages and Widgets

In a Scrivito-based web application, page and widget classes as well as instances of them are represented as React components. The examples in this guide use ES6 and JSX. All APIs described here are also available with ES5 and without JSX, though.

Page components

Pages are instances of Scrivito object classes that are based on the Obj model class Scrivito provides. For rendering the instances of a page model class, a corresponding component needs to be provided. First, let’s take a look at this simple page model as an example:

import * as Scrivito from 'scrivito';

Scrivito.provideObjClass('BlogPostPage', {
  attributes: {
    title: "string",
    author: "string",
    body: "html",
  }
});

To define a component for such a class, use the Scrivito.provideComponent function, like so:

import * as React from 'react';
import * as Scrivito from 'scrivito';

Scrivito.provideComponent('BlogPostPage', ({ page }) =>
  <div>
    <h1>{ page.get('title') }</h1>
    <span>By: { page.get('author') }</span>
    <div>{ page.get('body') }</div>
  </div>
);

Page components can also be stateful and use the full React component API. For this, pass a React.Component class to Scrivito.provideComponent. The component will then receive the page to render as props.page.

Widget components

Defining widget components is similar to defining page components:

import * as Scrivito from 'scrivito';

Scrivito.provideWidgetClass('HeadlineWidget', {
  attributes: {
    headline: "string"
  }
});

Analogous to Obj being the base class of all page classes, Widget is the base class of all widget classes. Again Scrivito.provideComponent is used for creating a component for rendering instances of this HeadlineWidget class:

import * as React from 'react';
import * as Scrivito from 'scrivito';

Scrivito.provideComponent('HeadlineWidget', ({ widget }) =>
  <h1>{ widget.get('headline') }</h1>;
);

That’s all! A HeadlineWidget is now rendered using the markup provided above.

If you need to handle state or events using React’s component API in your widget component, you can pass a React.Component class to Scrivito.provideComponent instead of a functional component. In this case, the widget to render is passed to the component via props.widget. See also Using React Components with Scrivito’s Model Classes.

Making content editable

One thing is still missing from the component examples above: CMS content gets rendered, but it cannot be edited. In order to enable in-place editing, a special helper component, Scrivito.ContentTag, is available. Let’s revise the above widget component to make its instances editable:

import * as React from 'react';
import * as Scrivito from 'scrivito';

Scrivito.provideComponent('HeadlineWidget', ({ widget }) =>
  <Scrivito.ContentTag tag="h1" content={ widget } attribute="headline"/>
);

The Scrivito.ContentTag component expects either a Widget or an Obj instance to be passed in via content, and the name of the attribute whose value should be rendered.

By default, it renders a <div> tag, containing the DOM representation of the content of the given attribute. In the example above, a string attribute is passed in, causing the (escaped) string contents to be put into the DOM.

The tag to be rendered can be customized using the tag property. You can also customize the DOM representation of the attribute value by providing child elements to <Scrivito.ContentTag>, like so:

<Scrivito.ContentTag content={ page } attribute="tags">
  { widget.get('tags').map(tag => 
      <span key={ tag }>
        { tag }
      </span> 
  }
</Scrivito.ContentTag>

The result would be something like this:

<div><span>Tag 1</span><span>Tag 2</span></div>

Rendering widgets

Another important use case of Scrivito.ContentTag is to render widgets from attributes of the widgetlist type:

<Scrivito.ContentTag content={ myPage } attribute="myWidgetlist" />

In this case, Scrivito simply renders all widgets in the widgetlist attribute using the components that have been registered for them by means of provideComponent.

Rendering images

For convenience, Scrivito offers the Scrivito.ImageTag component for rendering images:

<Scrivito.ImageTag content={ myImageObj } />

This component basically generates the following markup which you could also put down manually, of course:

<img src={ myImageObj.get('blob').url } />

However, in contrast to the <img> tag provided manually, the ImageTag component makes the image editable, optimizes image loading, and resizes images dynamically to speed up their delivery.

Using the optional attribute property, you can also pass in the name of an attribute of the reference type. An attribute of this type is typically used in an image widget for pointing to the image object associated with it. This is how one would implement a simple image widget:

import * as React from 'react';
import * as Scrivito from 'scrivito';

Scrivito.provideWidgetClass('ImageWidget', {
  attributes: {
    image: "reference",
  }
});

Scrivito.provideComponent('ImageWidget', ({ widget }) => 
  <Scrivito.ImageTag content={ widget } attribute=”image” />
);

In summary ...

Pages and widgets are based on object and widget model classes. Object and widget instances are rendered by components provided for these classes. Typically, those components use Scrivito.ContentTag and other helper components built into Scrivito to render page and widget attributes and make them editable.