Listing

Advanced

Lazy loading the bridge, authentication with getAccessToken, and preventing reloads

How Hydra Works

How Hydra separates editing from rendering using an iframe bridge, and a guide to building a frontend

Accordion

The accordion contains other blocks in an accordion behavior layout.

Block Reference Layout

Template for code examples at the bottom of block reference pages

Button

The button block shows a button for which a link (internal or external) can be stored. The button can be displayed left, right or center and have a background color.

Click to add image
Advanced

Lazy loading the bridge, authentication with getAccessToken, and preventing reloads

Read more
Click to add image
How Hydra Works

How Hydra separates editing from rendering using an iframe bridge, and a guide to building a frontend

Read more
Click to add image
Accordion

The accordion contains other blocks in an accordion behavior layout.

Read more
Click to add image
Block Reference Layout

Template for code examples at the bottom of block reference pages

Read more
Click to add image
Button

The button block shows a button for which a link (internal or external) can be stored. The button can be displayed left, right or center and have a background color.

Read more
Click to add image
Docs

Key concepts behind Hydra's visual headless CMS architecture

Read more
Image

Developer Reference

Schema

Pass this object inside the blocks option when calling initBridge() to register this block type with the admin UI. See Custom Blocks for the full setup guide.

{
  "listing": {
    "itemTypeField": "variation",
    "schemaEnhancer": {
      "inheritSchemaFrom": {
        "mappingField": "fieldMapping",
        "defaultsField": "itemDefaults",
        "filterConvertibleFrom": "@default",
        "title": "Item Type",
        "default": "summary"
      }
    }
  },
  "summary": {
    "fieldMappings": {
      "@default": {
        "@id": "href",
        "title": "title",
        "description": "description",
        "image": "image"
      }
    },
    "blockSchema": {
      "properties": {
        "href": {
          "title": "Link",
          "widget": "url"
        },
        "title": {
          "title": "Title"
        },
        "description": {
          "title": "Description",
          "widget": "textarea"
        },
        "image": {
          "title": "Image",
          "widget": "url"
        },
        "date": {
          "title": "Date",
          "widget": "date"
        }
      }
    }
  },
  "default": {
    "fieldMappings": {
      "@default": {
        "@id": "href",
        "title": "title",
        "description": "description"
      }
    },
    "blockSchema": {
      "properties": {
        "href": {
          "title": "Link",
          "widget": "url"
        },
        "title": {
          "title": "Title"
        },
        "description": {
          "title": "Description",
          "widget": "textarea"
        }
      }
    }
  }
}

JSON Block Data

Example JSON as stored in the Plone content API. This is the data structure your component will receive in the block prop.

{
  "@type": "listing",
  "variation": "summary",
  "querystring": {
    "query": [
      {
        "i": "portal_type",
        "o": "plone.app.querystring.operation.selection.any",
        "v": [
          "Document"
        ]
      }
    ],
    "sort_on": "effective",
    "sort_order": "descending"
  }
}

{
  "@uid": "item-1",
  "@type": "summary",
  "href": "/news/my-article",
  "title": "My Article",
  "description": "Article summary text",
  "image": "/news/my-article/@@images/image-800x600.jpg"
}

Component

Render component for your frontend framework. Add this to your block renderer's switch/map so it handles this @type.

function ListingBlock({ block, blockId }) {
  const [items, setItems] = useState([]);

  useEffect(() => {
    async function load() {
      const fetchItems = ploneFetchItems({ apiUrl: API_URL });
      const result = await expandListingBlocks([blockId], {
        blocks: { [blockId]: block },
        fetchItems: { listing: fetchItems },
        itemTypeField: 'variation',
      });
      setItems(result.items);
    }
    load();
  }, [block.querystring]);

  return (
    <div data-block-uid={blockId} className="listing-block">
      {items.map((item, i) => (
        <BlockRenderer key={i} block={item} />
      ))}
    </div>
  );
}