# Table renderer

Learn more about enabling custom table-cell rendering in your app

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.

```js
import {
  FieldExtensionType,
  FieldExtensionFeature,
} from '@graphcms/uix-react-sdk';

const declaration = {
  extensionType: 'field',
  fieldType: FieldExtensionType.JSON,
  name: 'Custom JSON',
  features: [
    FieldExtensionFeature.FieldRenderer,
    FieldExtensionFeature.TableRenderer,
  ],
};
```

**Note:**

UI extensions declaration must be [re-loaded](https://hygraph.com/classic-docs/ui-extensions/getting-started/extension-declaration#applying-declaration-changes) every time the declaration changes.

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:

**React**

```js
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,
  ],
};

const CustomStringInput = () => {
  const { value, onChange, isTableCell } = useFieldExtension();
  if (isTableCell) {
    return <p>{value}</p>;
  }
  return (
    <input
      value={value}
      onChange={({ target: { value: val } }) => onChange(val)}
    />
  );
};

const Extension = () => {
  return (
    <Wrapper declaration={declaration}>
      <CustomStringInput />
    </Wrapper>
  );
};
```


## Multiple values

What happens if your extension supports lists? By combining the two features, `FieldExtensionFeature.TableRenderer` and [`FieldExtensionFeature.ListRenderer`](https://hygraph.com/classic-docs/ui-extensions/field-extension/list-renderer), you can determine how multiple-value fields should behave in content table.

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

```js
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:

```js
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:

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