# Field extension quickstart

Field extension quickstart, with a step by step explanation on how to build a demo UI extension.

## Introduction

A UI extension is a web app inside Hygraph. They allow you to add custom components in the content editor.

You can build any UI component, like [basic inputs](https://github.com/hygraph/hygraph-examples/tree/master/uix-basic-input), [image pickers](https://github.com/hygraph/hygraph-examples/tree/master/uix-cloudinary-input), and [conditional fields](https://github.com/hygraph/hygraph-examples/tree/master/uix-conditional-field).

The sky is the limit.

## What you will build

The demo UI extension we will be building is the Hello UIX World. It's a basic input field to store text data.

You will also learn how to add custom settings, like an API Key to connect to a 3rd party service provider.

## Prerequisites

To complete this tutorial:

- You need the latest LTS version of Node.js installed on your machine. If you don't have it, you can [download it here](https://nodejs.org/en/download/)
- You should be comfortable using a command line tool and any IDE or text editor of your choice
- You should be familiar with JavaScript and React
- You need a free Hygraph account and a project. You can [signup here](https://app.hygraph.com/signup).

**Note:**
  If you're new to Hygraph, [create a
  project](https://app.hygraph.com/create?template=da55760a30f64230904493051ce39062)
  using the Blog Starter template

## What you will learn

In this tutorial, you will learn:

- How to create a UI Extension
- How to run and test the UI Extension on your local development environment
- How to add the UI Extension to a Model
- How to add custom settings to your UI Extension, like an API Key
- How to deploy your UI Extension to Vercel
- How to install and use your UI Extension in production
- (Bonus) How to display data into table content view

## Step 1: Creating a UI extension

**1. Create React project**

```bash
# create a project with npm
npx create-react-app hello-uix-guide

# change directory
cd hello-uix-guide
```

Now, open the project in the code editor of your preference.

**2. Create a new React component**

```jsx
// src/extensions/HelloUixWorld.js

import { useState, useEffect } from 'react';

const MyField = () => {
  const [localValue, setLocalValue] = useState('');

  useEffect(() => {
    // Will be used soon
  }, [localValue]);

  return (
    <input value={localValue} onChange={(e) => setLocalValue(e.target.val)} />
  );
};

const HelloUixWorld = () => {
  return <MyField />;
};

export default HelloUixWorld;
```

**3. Import the component into your app**

```jsx
// src/App.js

import HelloUixWorld from './extensions/HelloUixWorld';

function App() {
  return <HelloUixWorld />;
}

export default App;
```

**Note:**

You can replace all content of App.js with the code above

**4. Run the app locally**

```
npm run start
```

By visiting [http://localhost:3000](http://localhost:3000) on your browser, you should see a very basic HTML input field.

Now, let's transform it into a Hygraph UI Extension!

## Step 2: Using Hygraph React SDK

**1. Installing the React SDK**

In order to transform it into a UI Extension, you must install Hygraph React SDK as a dependency on your project. You can do it running the following command on your Terminal:

```bash
yarn add @graphcms/uix-react-sdk
```

**2. Adding React SDK**

Now, let's import some SDK components, hooks and enumerations from Hygraph SDK.

Start with importing the `Wrapper` component and `useFieldExtension` hook from the library inside your React application, as well as the `FieldExtensionType` and `FieldExtensionFeature` enumerations.

You should add the following code at the top of the `HelloUixWorld.js` file. Remember to import `useEffect` hook at the top.

```jsx
// src/extensions/HelloUixWorld.js

import { useState, useEffect } from 'react';

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

Then, add `useFieldExtension` hook into `MyField` and adjust the code accordingly, like the following example:

```jsx
const MyField = () => {
  const { value, onChange } = useFieldExtension();
  const [localValue, setLocalValue] = useState(value || '');

  useEffect(() => {
    onChange(localValue);
  }, [localValue, onChange]);

  return (
    <input value={localValue} onChange={(e) => setLocalValue(e.target.value)} />
  );
};
```

Then, we need to add the [extension declaration](https://hygraph.com/classic-docs/ui-extensions/getting-started/extension-declaration):

```jsx
const declaration = {
  extensionType: 'field',
  fieldType: FieldExtensionType.STRING,
  features: [FieldExtensionFeature.FieldRenderer],
  name: 'Hello UIX World',
};
```

Finally, let's wrap our custom input field with the `Wrapper` component:

```jsx
const HelloUixWorld = () => {
  return (
    <Wrapper declaration={declaration}>
      <MyField />
    </Wrapper>
  );
};
```

Your complete custom UI Extension code should look like this:

```jsx
// src/extensions/HellowUixWorld.js

import { useState, useEffect } from 'react';

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

const MyField = () => {
  const { value, onChange } = useFieldExtension();
  const [localValue, setLocalValue] = useState(value || '');

  useEffect(() => {
    onChange(localValue);
  }, [localValue, onChange]);

  return (
    <input value={localValue} onChange={(e) => setLocalValue(e.target.value)} />
  );
};

const declaration = {
  extensionType: 'field',
  fieldType: FieldExtensionType.STRING,
  features: [FieldExtensionFeature.FieldRenderer],
  name: 'Hello UIX World',
};

const HelloUixWorld = () => {
  return (
    <Wrapper declaration={declaration}>
      <MyField />
    </Wrapper>
  );
};

export default HelloUixWorld;
```

**3. Testing UI extension on Localhost**

At this point, you should see the "SDK connection error, check logs" message in your browser. The reason is that it's expected to be running from Hygraph application. So, you should just ignore this message.

Now, let's install and test your new UI Extension on localhost by following these steps:

1.  Go to [https://app.hygraph.com](https://app.hygraph.com) and open any existing project

          **Note:**

          If you don't have a project yet, [use the Blog starter](https://app.hygraph.com/create?template=da55760a30f64230904493051ce39062)

2.  Navigate to **Project Settings > UI Extensions**
3.  Click on **Add UI Extension** button
4.  On **Extension URL** field, enter [http://localhost:3000](http://localhost:3000)
5.  Click on **Run compatibility test** button
6.  Finally, fill in your custom UI Extension name and description, and click on **Authorize & Install**.

If everything went well, you should see something like this:

![UI Extension Install](https://hygraph.com/images/classic-docs/ui-extensions/building-ui-extensions/ui-extension-install.png)

## Step 3: Adding custom UI extension to a model

Now, it's time to use your new UI Extension.

Follow these steps:

1. Go to **Schema**
2. On the left, click on the model you want to add the new UI Extension
3. On the right, you should see your new UI Extension under Strings fields
4. Click on your UI Extension to add it into the model
5. Enter some information like Display Name, API ID, etc
6. When you're ready, click on **Create** button

## Step 4: Using your custom UI extension

1. On the left navigation, go to **Content**
2. Select the model you've added the UI extension in the previous step
3. Click on **Create Item** button on the top right corner or **Edit** and existing one
4. Enter some text into the field and click on **Save**

**Note:**

You can see your new data on API Playground

## Step 5: Adding custom settings to a UI extension

Let's say you are building a UI Extension that needs an API Key and you want to prompt user to enter this information during the installation process.

You can do it by adding the config property to the [extension declaration](https://hygraph.com/classic-docs/ui-extensions/getting-started/extension-declaration):

1. On your Code Editor, open `HelloUixWorld.js` file
2. Add the following code into `const declaration` and save the file

```jsx
// src/extensions/HelloUixWorld.js

const declaration = {
  extensionType: 'field',
  fieldType: FieldExtensionType.STRING,
  features: [FieldExtensionFeature.FieldRenderer],
  name: 'Hello UIX World',
  config: {
    API_KEY: {
      type: 'string',
      displayName: 'API Key',
      description: 'API Key for this UI Extension',
      required: true,
    },
  },
};
```

1. Go back to your browser and open your project dashboard
2. Go to **Project Settings > UI Extension**
3. On Hello UIX World, click on the **three dots** and then click on **Edit**
4. Click **Refresh** next to the **Edit** button

Now, you should see the new API Key field. Once it's a required one, enter any text and hit the **Update** button.

![UI Extension Custom Settings](https://hygraph.com/images/classic-docs/ui-extensions/building-ui-extensions/ui-extension-custom-settings.png)

## Step 6: Deploying your UI extension

To use your UI Extension in a live website or application, you should host it somewhere on the internet. For the sake of this tutorial, we will deploy it on Vercel. But you can use any hosting service.

Do the following steps:

1. Open your Terminal
2. Navigate into your project root directory and run `npx vercel`

```bash
cd hello-uix-world
npx vercel
```

1. Follow the step-by-step guide on your Terminal
2. Once it's deployed, the extension URL will be automatically copied to your clipboard
3. Open your project dashboard on your browser
4. Go to **Project Settings > UI Extension**
5. On Hello UIX World, click on the **three dots,** then click on **Edit**
6. Click on **Edit** button next to the Extension URL field
7. Replace **Extension URL** field with the new URL
8. Click on the **OK** button
9. Finally, click on the **Update** button

## Bonus Step: Displaying the data in content table view

Let's say you want to display the data stored in your custom UI extension field in the content table view.

![UI Extension Table Renderer](https://hygraph.com/images/classic-docs/ui-extensions/building-ui-extensions/ui-extension-table-renderer.png)

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

```jsx
// src/extensions/HelloUixWorld.js

const declaration = {
  extensionType: 'field',
  fieldType: FieldExtensionType.STRING,
  features: [
    FieldExtensionFeature.FieldRenderer,
    FieldExtensionFeature.TableRenderer, // Enables custom table-cell rendering
  ],
  name: 'Hello UIX World',
  config: {
    API_KEY: {
      type: 'string',
      displayName: 'API Key',
      description: 'API Key for this UI Extension',
      required: true,
    },
  },
};
```

**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.

Therefore, change `MyField()` method like the following code:

```jsx
// src/extensions/HelloUixWorld.js

const MyField = () => {
  const { value, onChange, isTableCell } = useFieldExtension();
  const [localValue, setLocalValue] = useState(value || '');

  useEffect(() => {
    // onChange doesn't works on table cell
    if (!isTableCell) {
      onChange(localValue);
    }
  }, [localValue, onChange, isTableCell]);

  // Display value in the table content
  if (isTableCell) {
    return <p>{value}</p>;
  }

  return (
    <input value={localValue} onChange={(e) => setLocalValue(e.target.value)} />
  );
};
```

## Congratulations!

You've just learned how to build custom UI Extensions for Hygraph!

Take a look into these [UI extensions examples](https://github.com/hygraph/hygraph-examples#ui-extensions) for inspiration.

**Additional resources**

- [React SDK](https://hygraph.com/classic-docs/ui-extensions/libraries/react-sdk)
- [Extension declaration](https://hygraph.com/classic-docs/ui-extensions/getting-started/extension-declaration)
- [Table renderer](https://hygraph.com/classic-docs/ui-extensions/field-extension/table-renderer)
