The first step is to implement the itemFormOutlets
hook, to declare our intent to add the outlet to the form:
import { connect, ItemFormOutletsCtx } from 'datocms-plugin-sdk';connect({itemFormOutlets(model, ctx: ItemFormOutletsCtx) {return [{id: 'myOutlet',initialHeight: 100,},];},});
The initialHeight
property sets the initial height of the frame, while the plugin itself is loading. It can also be useful to completely hide the outlet, by passing the value zero to it.
The code above will add the outlet to the form of every record in our project, but you can also add some settings to the plugin to ie. let the final user pick only some specific models:
itemFormOutlets(model, ctx: ItemFormOutletsCtx) {const { modelApiKeys } = ctx.plugin.attributes.parameters;if (!modelApiKeys.includes(model.attributes.api_key)) {// Don't add the outlet!return [];}// Add the outlet!}
The final step is to actually render the outlet itself by implementing the renderItemFormOutlet
hook.
Inside of this hook we can initialize React and render a custom component, passing down as a prop the second ctx
argument, which provides a series of information and methods for interacting with the main application:
import React from 'react';import ReactDOM from 'react-dom';import { connect, RenderItemFormOutletCtx, ItemFormOutletsCtx } from 'datocms-plugin-sdk';connect({itemFormOutlets(model, ctx: ItemFormOutletsCtx) { ... },renderItemFormOutlet(outletId,ctx: RenderItemFormOutletCtx,) {ReactDOM.render(<React.StrictMode><MyCustomOutlet ctx={ctx} /></React.StrictMode>,document.getElementById('root'),);},});
A plugin might render different types of form outlets, so we can use the outletId
argument to know which one we are requested to render, and write a specific React component for each of them.
import { Canvas } from 'datocms-react-ui';function MyCustomOutlet({ ctx }) {return (<Canvas ctx={ctx}>Hello from the record form outlet!</Canvas>);}
If you want to render something inside the outlet, it is important to wrap the content inside the Canvas
component, so that the iframe will continuously auto-adjust its size based on the content we're rendering, and to give our app the look and feel of the DatoCMS web app.
If you want the outlet to be hidden from the interface, just return null
and set an initialHeight: 0
in the itemFormOutlets
hook.
Record collection outlets allow you to add custom areas to the page that displays a collection of records for a specific model.
The implementation is exactly the same as the one we just saw for the Record Form Outlets. The only thing that changes is the hooks to be used:
To declare the intention to offer Record Collection Outlets, use itemCollectionOutlets
;
To actually render the outlets, use renderItemCollectionOutlet
.
Here's a full example:
import React from 'react';import ReactDOM from 'react-dom';import { connect, ItemCollectionOutletsCtx, RenderItemCollectionOutletCtx } from 'datocms-plugin-sdk';import { Canvas, Button } from 'datocms-react-ui';connect({itemCollectionOutlets(model, ctx: ItemCollectionOutletsCtx) {// Optional: Add conditions to show the outlet only for specific modelsconst { modelApiKeys } = ctx.plugin.attributes.parameters;if (!modelApiKeys.includes(model.attributes.api_key)) {return [];}return [{id: 'myCollectionOutlet',initialHeight: 100,},];},renderItemCollectionOutlet(outletId, ctx: RenderItemCollectionOutletCtx) {render(<MyCustomCollectionOutlet ctx={ctx} />);},});function MyCustomCollectionOutlet({ ctx }) {return (<Canvas ctx={ctx}><h3>Custom Collection Outlet</h3><p>This outlet appears above the record listing for {ctx.itemType.attributes.name}.</p></Canvas>);}
renderItemFormOutlet()
The following properties and methods are available in the ctx
argument:
renderItemCollectionOutlet()
The following properties and methods are available in the ctx
argument: