Join us live as we unveil the all new Hygraph Studio!

Hygraph
Docs

Table renderer

You can define how custom field values are displayed in the content table.

To enable custom table-cell rendering in your app, add FieldExtensionFeature.TableRenderer to the features array in the extension declaration.

import {
FieldExtensionType,
FieldExtensionFeature,
} from '@graphcms/uix-react-sdk';
const declaration = {
extensionType: 'field',
fieldType: FieldExtensionType.JSON,
name: 'Custom JSON',
features: [
FieldExtensionFeature.FieldRenderer,
FieldExtensionFeature.TableRenderer,
],
};

The SDK provides a isTableCell boolean that you can use to detect that the current extension instance is rendered in the content table:

How you handle table-cell rendering is up to you. Hygraph will only enforce a cell height of 60px in order to preserve other fields' functionality in the table layout.

Let's emulate a simple string field preview that conditionally displays the value in a paragraph:

#Multiple values

What happens if your extension supports lists? By combining the two features, FieldExtensionFeature.TableRenderer and FieldExtensionFeature.ListRenderer, you can determine how multiple-value fields should behave in content table.

Let us augment the previous example to account for list values:

import {
Wrapper,
useFieldExtension,
FieldExtensionType,
FieldExtensionFeature,
} from '@graphcms/uix-react-sdk';
const declaration = {
extensionType: 'field',
fieldType: FieldExtensionType.STRING,
name: 'Custom string',
features: [
FieldExtensionFeature.FieldRenderer,
FieldExtensionFeature.TableRenderer,
FieldExtensionFeature.ListRenderer,
],
};
const CustomStringInput = () => {
const {
value,
onChange,
isTableCell,
field: { isList },
} = useFieldExtension();
if (isTableCell) {
if (isList) {
return (
<div>
{value.map((item) => (
<p>{item}</p>
))}
</div>
);
}
return <p>{value}</p>;
}
if (isList) {
return (
<input
value={value}
onChange={({ target: { value: val } }) => onChange([...value, val])}
/>
);
}
return (
<input
value={value}
onChange={({ target: { value: val } }) => onChange(val)}
/>
);
};
const Extension = () => {
return (
<Wrapper declaration={declaration}>
<CustomStringInput />
</Wrapper>
);
};

#Preview expansion

The example above would work for simple cases, but you'll likely need more space than a table cell allows.

For those cases, the SDK provides you with tools to display the content of a custom field in full-screen mode.

Extract the expand handler that takes a boolean as an argument and isExpanded prop by calling the useFieldExtension hook:

const { isTableCell, expand, isExpanded } = useFieldExtension();

Instead of displaying the value directly in the table cell, you can now render a button that would expand the preview. A basic example would be something like this:

if (isTableCell) {
if (isExpanded) {
return (
<div>
<p>{value}</p>
<button onClick={() => expand(false)}>Close</button>
<div>
);
} else {
return (
<button onClick={() => expand(true)}>
Preview
</button>
);
}
}