> ## Documentation Index
> Fetch the complete documentation index at: https://translations.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> JavaScript、HTML、CSS を使用して、特定のロジックや UI が必要なフィールドをカスタムコンポーネントで作成する方法を説明します。

# カスタムフィールドコンポーネント

<Frame>
  <img src="https://mintcdn.com/translations/3nS3prIggmJG9TUI/docs/images/cdy7uua7fh8z/3bZUItvx7VQG1AUuTah1V0/6ba3b7e9909d189f418cdc85a5ed53b9/custom-field.png?fit=max&auto=format&n=3nS3prIggmJG9TUI&q=85&s=95b1437db66cd9cde17d02d58affdce8" alt="Dashboard > Actions > Forms > カスタムフィールド" data-og-width="1408" width="1408" data-og-height="850" height="850" data-path="docs/images/cdy7uua7fh8z/3bZUItvx7VQG1AUuTah1V0/6ba3b7e9909d189f418cdc85a5ed53b9/custom-field.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/translations/3nS3prIggmJG9TUI/docs/images/cdy7uua7fh8z/3bZUItvx7VQG1AUuTah1V0/6ba3b7e9909d189f418cdc85a5ed53b9/custom-field.png?w=280&fit=max&auto=format&n=3nS3prIggmJG9TUI&q=85&s=a48fc426395506412dd8f92f85cdef5c 280w, https://mintcdn.com/translations/3nS3prIggmJG9TUI/docs/images/cdy7uua7fh8z/3bZUItvx7VQG1AUuTah1V0/6ba3b7e9909d189f418cdc85a5ed53b9/custom-field.png?w=560&fit=max&auto=format&n=3nS3prIggmJG9TUI&q=85&s=3975b492b7a9db0a984c74c03ed767e6 560w, https://mintcdn.com/translations/3nS3prIggmJG9TUI/docs/images/cdy7uua7fh8z/3bZUItvx7VQG1AUuTah1V0/6ba3b7e9909d189f418cdc85a5ed53b9/custom-field.png?w=840&fit=max&auto=format&n=3nS3prIggmJG9TUI&q=85&s=9e0c23270d3e16dda762e669fc2a740f 840w, https://mintcdn.com/translations/3nS3prIggmJG9TUI/docs/images/cdy7uua7fh8z/3bZUItvx7VQG1AUuTah1V0/6ba3b7e9909d189f418cdc85a5ed53b9/custom-field.png?w=1100&fit=max&auto=format&n=3nS3prIggmJG9TUI&q=85&s=8a4fd3d926b9030f84c4779efd38cd2c 1100w, https://mintcdn.com/translations/3nS3prIggmJG9TUI/docs/images/cdy7uua7fh8z/3bZUItvx7VQG1AUuTah1V0/6ba3b7e9909d189f418cdc85a5ed53b9/custom-field.png?w=1650&fit=max&auto=format&n=3nS3prIggmJG9TUI&q=85&s=4938b324f243a4341c73fb741175c62e 1650w, https://mintcdn.com/translations/3nS3prIggmJG9TUI/docs/images/cdy7uua7fh8z/3bZUItvx7VQG1AUuTah1V0/6ba3b7e9909d189f418cdc85a5ed53b9/custom-field.png?w=2500&fit=max&auto=format&n=3nS3prIggmJG9TUI&q=85&s=582b9437250ab7132d0d73adf82bc951 2500w" />
</Frame>

カスタムフィールドを使用すると、フォームの外観や操作感を拡張し、JavaScript、HTML、CSS を使って高度なロジックを追加できます。

カスタムフィールドには、フォームへのデータの受け渡し、フロントエンドとバックエンドのバリデーションの追加、focus や blur などの一般的なイベントの処理を容易にする内部メソッドが用意されています。

カスタムフィールドを使用すると、次のようなものを作成できます。

* カスタムのデータ構造を持つフィールド。

  * **例**: オブジェクト、文字列の配列
* サードパーティのウィジェットを使用するフィールド。

  * **例**: Google Address autocomplete
* 他のフィールドの表示/非表示を切り替えるロジックを持つフィールド。
* 値の取得に外部 API が必要なフィールド。

<Warning>
  カスタムフィールドを使用するには、[カスタムドメイン](/ja/docs/customize/custom-domains)を有効にする必要があります。カスタムドメイン外でカスタムフィールドを含むフォームをレンダリングすると、エラーが表示されます。
</Warning>

<div id="custom-field-settings">
  ## カスタムフィールド設定
</div>

カスタムフィールド設定は次のとおりです。

<div id="params">
  ### Params
</div>

カスタムフィールドのソースコードで参照するキーと値のペアを追加します。キーと値のペアには、フォームフィールドの[変数](/ja/docs/customize/forms/variables)を含めることができます。

<Frame>
  <img src="https://mintcdn.com/translations/6GE5Z24GDCZehiJ9/docs/images/cdy7uua7fh8z/6VEtliKd20ZF4MJKhvB5Z0/e1b3b5df4860d013d1e3eb79d1174b35/params.png?fit=max&auto=format&n=6GE5Z24GDCZehiJ9&q=85&s=1b013cace644247d8f22e9c3175e5b47" alt="" width="821" height="320" data-path="docs/images/cdy7uua7fh8z/6VEtliKd20ZF4MJKhvB5Z0/e1b3b5df4860d013d1e3eb79d1174b35/params.png" />
</Frame>

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Param の値は、フォームで `init()` メソッドが呼び出された後でのみ利用できます。
</Callout>

**例**:

以下の例では、カスタムフィールドの param 設定に、`symbol={{fields.symbol}}` と `separator=,` というキーと値のペアが設定されています。

```javascript lines expandable theme={null}
function CustomComponent(context) {
  const input = document.createElement('input');
  let mask = null;

  function mountComponent() {
    /** getParams() メソッドは、入力フィールドに設定したパラメータを返します */
    const config = context.custom.getParams();
    const { symbol, separator } = config;

    mask = IMask(input,
    {
      mask: `${symbol}num`,
      blocks: {
        num: {
          mask: Number,
          thousandsSeparator: separator,
        }
      }
    });
  }

  return {
    /** フィールドの作成時に一度だけ呼び出されます */
    init() {
      mountComponent();
      return input;
    },
    ...
  };
}
```

<div id="source-code">
  ### ソースコード
</div>

カスタムフィールドにJavaScriptコードを追加します。

<Frame>
  <img src="https://mintcdn.com/translations/mMSz-RNYLuOm2GmQ/docs/images/cdy7uua7fh8z/TMuY21ILSxBiBWv792cTB/97e9855145d7b52fc33ed60249e86642/source-code.png?fit=max&auto=format&n=mMSz-RNYLuOm2GmQ&q=85&s=88f456ff9461b3c4cba9cba9a07d1b5e" alt="" width="958" height="405" data-path="docs/images/cdy7uua7fh8z/TMuY21ILSxBiBWv792cTB/97e9855145d7b52fc33ed60249e86642/source-code.png" />
</Frame>

**例**:

```javascript lines theme={null}
function customInput() {
  const input = document.createElement('input');
  input.type = 'text';

  return {
    init() {
      return input;
    },

    block() {
      input.disabled = true;
    },

    unblock() {
      input.disabled = false;
    },

    getValue() {
      return input.value;
    }
  };
}
```

<div id="json-schema">
  ### JSON Schema
</div>

デフォルトでは、カスタムフィールドはどのような形式の値でも受け付けます。ただし、値をサーバー側で検証するために [JSON Schema](https://json-schema.org/) を使用できます。

<Frame>
  <img src="https://mintcdn.com/translations/MV7tE-x71x8RWRES/docs/images/cdy7uua7fh8z/5iQfwWq8Scx11s1fcSONvK/d7af907f575095d66558ee2631c73113/json-schema.png?fit=max&auto=format&n=MV7tE-x71x8RWRES&q=85&s=e05f71d747f278a2308e6bb77c3d1f6d" alt="" width="672" height="351" data-path="docs/images/cdy7uua7fh8z/5iQfwWq8Scx11s1fcSONvK/d7af907f575095d66558ee2631c73113/json-schema.png" />
</Frame>

**例**:

```json lines theme={null}
{
  "type": "array",
  "items": {
    "type": "string"
  },
  "minItems": 2
}
```

複雑なバリデーション要件に対応するには、[flow](/ja/docs/customize/forms/flows)を使用できます。

<div id="css">
  ### CSS
</div>

カスタムフィールドに CSS を追加します。

<Frame>
  <img src="https://mintcdn.com/translations/xwVvTWJUElMm5YAK/docs/images/cdy7uua7fh8z/lC4w1THpVDD32Ke6IsXrl/e1371beeed09d5f12b6656d397c3b692/css.png?fit=max&auto=format&n=xwVvTWJUElMm5YAK&q=85&s=69e9937c82fe8d0fa2c2add0d1ff64b8" alt="" width="812" height="343" data-path="docs/images/cdy7uua7fh8z/lC4w1THpVDD32Ke6IsXrl/e1371beeed09d5f12b6656d397c3b692/css.png" />
</Frame>

<div id="custom-field-handlers">
  ## カスタムフィールドハンドラー
</div>

これらのハンドラーを使用すると、フィールドにカスタムの動作を追加できます。

<div id="init">
  ### init()
</div>

フィールドの作成時に一度だけ呼び出され、Params 設定で構成した `params` の値が渡されます。

HTML 要素、文字列、または何も返しません。

**例**:

```javascript lines theme={null}
const input = document.createElement('input');
input.type = 'text';

init() {
  return input;
}
```

<div id="update">
  ### update()
</div>

ユーザーが同じフォームステップに再度アクセスしたときに呼び出されます。

このオプションは、UI ロジックを再レンダリングする必要がある場合や、変更されている可能性のある `params` の値を更新する必要がある場合に便利です。

<div id="onfocus">
  ### onFocus()
</div>

フォーカスがカスタムフィールドのHTML要素に入ると呼び出されます。

<div id="onblur">
  ### onBlur()
</div>

カスタムフィールドの HTML 要素からフォーカスが外れたときに呼び出されます。

<div id="getvalue">
  ### getValue()
</div>

フォームがカスタムフィールドの値を1回以上取得する必要がある場合に呼び出されます。通常は、ユーザーがフォームステップを送信したときに実行されます。クライアント側のバリデーションを行う必要がある場合は、エラーをスローすることで、ユーザーにカスタムエラーメッセージを表示できます。

**例:**

```javascript lines theme={null}
function customTextInput() {
  const input = document.createElement('input');
  input.type = 'text';

  return {
    init() {
      return input;
    },

    getValue() {
      if (input.value !== 'Auth0') {
        throw new Error('The value must be Auth0')
      }

      return input.value;
    }
  };
}
```

<div id="block">
  ### block()
</div>

カスタムフィールドをブロックする必要がある場合に呼び出されます。通常は、ユーザーがフォームステップを送信し、そのデータがバックエンドで処理されている間に実行されます。

<div id="unblock">
  ### unblock()
</div>

カスタムフィールドのブロックを解除する必要がある場合に呼び出されます。通常は、ユーザーがフォームステップを送信した後、または検証エラーによりバックエンド側でのデータ処理が停止した後に実行されます。

<div id="getscripts">
  ### getScripts()
</div>

フォームが `init()` メソッドを呼び出す前に、読み込みが完了していることが保証される URL の一覧を返します。

**例**:

```js lines theme={null}
getScripts() {
  return ['https://example.com/script_a.js', 'https://example.com/script_b.js'];
}
```

<div id="context-object">
  ## コンテキストオブジェクト
</div>

コンテキストオブジェクトを渡す場合は、これらのメソッドを使用してフォームやコンポーネント内のロジックを処理できます。

<div id="custom-methods">
  ### custom メソッド
</div>

<div id="contextcustomgetvalue">
  #### context.custom.getValue()
</div>

現在のカスタムフィールドの値を返します。

<div id="contextcustomsetvalue">
  #### context.custom.setValue()
</div>

現在のカスタムフィールドに値をセットします。

**例**:

```javascript lines theme={null}
function customInput(context) {
  const input = document.createElement('input');
  input.type = 'text';

  input.addEventListener('change', () => {
    context.custom.setValue(input.value);
  });

  return {
    init() {
      return input;
    },
  };
}
```

<div id="contextcustomcreateuid">
  #### context.custom.createUid()
</div>

現在のカスタムフィールドに対する一意の識別子を返します。

**例**:

```javascript lines theme={null}
function customInput(context) {
  const input = document.createElement('input');
  input.type = 'text';
  input.id = context.custom.createUid();

  return {
    init() {
      return input;
    },

    getValue() {
      return input.value;
    }
  };
}
```

<div id="contextcustomgetparams">
  #### context.custom.getParams()
</div>

現在のカスタムフィールド設定のパラメータを取得します。

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  パラメータ値は、フォームで `init()` メソッドが呼び出された後でのみ利用できます。
</Callout>

**例**:

```javascript lines theme={null}
function customInput(context) {
  // 関数のルートでパラメータにアクセスしても動作しません
  // const { defaultValue } = context.custom.getParams();
  // console.log(defaultValue); // undefined

  function buildInput() {
    const { defaultValue } = context.custom.getParams();
    const input = document.createElement('input');
    input.type = 'text';
    input.value = defaultValue;

    return input;
  }

  return {
    init() {
      return buildInput();
    },

    getValue() {
      return input.value;
    }
  };
}
```

<div id="form-methods">
  ### フォームメソッド
</div>

他のフィールドの値を取得したり、フォーム内の別のステップに移動したりするためにフォームを操作する必要がある場合は、次のフォームメソッドを使用できます。

<div id="contextformgetid">
  #### context.form.getId()
</div>

現在のフォームの一意の識別子を返します。

<div id="contextformgetroot">
  #### context.form.getRoot()
</div>

現在のフォームのルートとなるHTML要素を返します。

<div id="contextformgoforward">
  #### context.form.goForward()
</div>

フォームの次のステップに進みます。

<div id="contextformgoprevious">
  #### context.form.goPrevious()
</div>

前のフォームステップに移動します。

<div id="contextformisvalid">
  #### context.form.isValid()
</div>

フォームがすべてのクライアント側のバリデーションに合格しているかどうかを、ブール値で返します。

<div id="contextformvalidate">
  #### context.form.validate()
</div>

続行する前に、既存のフィールド値に対してクライアント側でバリデーションを実行します。フィールドがバリデーションを通過しない場合は、エラーメッセージが表示されます。

<div id="contextformgetallhiddenfields">
  #### context.form.getAllHiddenFields()
</div>

すべての非表示フィールドの値を格納したオブジェクトを返します。

<div id="contextformsethiddenfieldid-value">
  #### context.form.setHiddenField(id, value)
</div>

非表示フィールドの値を設定します。

| パラメータ   | 説明                     |
| ------- | ---------------------- |
| `id`    | *String*。非表示フィールドの ID。 |
| `value` | *String*。非表示フィールドの値。   |

<div id="contextformgetvalues">
  #### context.form.getValues()
</div>

すべてのフィールドと非表示フィールドの値を含むオブジェクトを返します。

<div id="contextformgetfieldid">
  #### context.form.getField(id)
</div>

指定したフィールドのインスタンスを返します。

* `getNode() | true` フィールドのルート HTML 要素を返します。
* `getValue()` フィールドの値を返します。
* `setRequired(boolean)` フィールドを必須に設定または解除します。

| Parameter | Description               |
| --------- | ------------------------- |
| `id`      | \*String \*. フィールドの ID 値。 |

**例**:

```javascript lines theme={null}
const fullName = context.form.getField('full_name');
const fullNameValue = fullName.getValue();
console.log(fullNameValue); // 山田太郎
```

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  `setRequired()` は、クライアント側でフィールドを必須に設定または解除するだけです。たとえば、あるフィールドの必須設定を解除しても、フィールド設定でそのフィールドが必須としてマークされている場合、値が入力されていなければフォームはエラーを返します。
</Callout>

<div id="custom-field-examples">
  ## カスタムフィールドの例
</div>

以下のセクションでは、フォームに追加できるカスタムフィールドの例を示します。

<div id="range-input-custom-field">
  ### 範囲入力のカスタムフィールド
</div>

あらかじめ定義された範囲内の値を返すカスタムフィールドです。

<Frame>
  <img src="https://mintcdn.com/translations/pvjQqAy3EB2TK6NP/docs/images/cdy7uua7fh8z/4afLZWM9MAXXti4F3Cuc3D/c6c6d33c650b7b9fde3de011feb82192/range-input-custom-field.png?fit=max&auto=format&n=pvjQqAy3EB2TK6NP&q=85&s=975aaade4577fdfa85070141250517a8" alt="" width="380" height="242" data-path="docs/images/cdy7uua7fh8z/4afLZWM9MAXXti4F3Cuc3D/c6c6d33c650b7b9fde3de011feb82192/range-input-custom-field.png" />
</Frame>

**ソースコード**:

```javascript lines theme={null}
function rangeInput() {
  const input = document.createElement('input');
  input.type = 'range';
  input.min= '0';
  input.max= '100';
  input.value = '0';

  return {
    init() {
      return input;
    },

    getValue() {
      return input.value;
    }
  };
}
```

<div id="color-input-custom-field">
  ### カラー入力のカスタムフィールド
</div>

色の16進数値を返すカスタムフィールドです。

<Frame>
  <img src="https://mintcdn.com/translations/MV7tE-x71x8RWRES/docs/images/cdy7uua7fh8z/5HAWLZJmCRlyl3dIrgzgWv/c602ccc1662d40d03898dcaa94d213dc/color-input-custom-field.png?fit=max&auto=format&n=MV7tE-x71x8RWRES&q=85&s=933a4b444ad650f36e106deadd1bb867" alt="" width="376" height="262" data-path="docs/images/cdy7uua7fh8z/5HAWLZJmCRlyl3dIrgzgWv/c602ccc1662d40d03898dcaa94d213dc/color-input-custom-field.png" />
</Frame>

**ソースコード**:

```javascript lines theme={null}
function colorInput() {
  const input = document.createElement('input');
  input.type = 'color';
  input.value = '#20c5a0';

  return {
    init() {
      return input;
    },

    getValue() {
      return input.value;
    },
  };
}
```

<div id="autocomplete-input-custom-field-using-values-from-api">
  ### API の値を使用したオートコンプリート入力カスタムフィールド
</div>

サードパーティ API を使用してオートコンプリートの値を返すカスタムフィールドです。

<Frame>
  <img src="https://mintcdn.com/translations/xwVvTWJUElMm5YAK/docs/images/cdy7uua7fh8z/l0lvyJgPLrHrLT8rpR6IF/800868d966ef5b64effbb6a3b0cabf94/autocomplete-api.png?fit=max&auto=format&n=xwVvTWJUElMm5YAK&q=85&s=9e51ffb16f6833be5abd0fc89f51e15d" alt="" width="380" height="294" data-path="docs/images/cdy7uua7fh8z/l0lvyJgPLrHrLT8rpR6IF/800868d966ef5b64effbb6a3b0cabf94/autocomplete-api.png" />
</Frame>

**ソースコード**:

```javascript lines expandable theme={null}
function textInputWithAutocomplete(context) {
  const input = document.createElement('input');
  input.type = 'text';

  function populateInputValue(json) {
    const { city } = json;

    input.value = city;
  }

  function fetchIpInfo() {
    const url = 'https://ipinfo.io/json';
    fetch(url)
      .then((res) => res.json())
      .then((json) => populateInputValue(json));
  }

  return {
    init() {
      fetchIpInfo();
      return input;
    },

    getValue() {
      return input.value;
    },
  };
}
```

<div id="dynamic-dropdown-custom-field-using-values-from-api">
  ### API の値を使用する動的なドロップダウン カスタムフィールド
</div>

サードパーティ API を使用して、動的なドロップダウン リストから値を返すカスタムフィールドです。

<Frame>
  <img src="https://mintcdn.com/translations/6GE5Z24GDCZehiJ9/docs/images/cdy7uua7fh8z/6gwOMuZaYi3dh0bkrxnKy9/33172d00e3933c74954a8ac3befaff7f/dropdowncustomfield.png?fit=max&auto=format&n=6GE5Z24GDCZehiJ9&q=85&s=85158ae8120598750cdf07f5bbc5041a" alt="" width="379" height="254" data-path="docs/images/cdy7uua7fh8z/6gwOMuZaYi3dh0bkrxnKy9/33172d00e3933c74954a8ac3befaff7f/dropdowncustomfield.png" />
</Frame>

**ソースコード**:

```javascript lines expandable theme={null}
function dynamicDropdown() {
  const select = document.createElement('select');
  select.classList.add('af-stringField-input');

  function buildOption(data) {
    const { name: { first } } = data;
    const option = document.createElement('option');
    option.value = first;
    option.innerText = first;

    return option;
  }

  function populateNames(json) {
    const { results } = json;

    results.forEach((o) => {
      const option = buildOption(o);

      select.appendChild(option);
    });
  }

  function fetchNames() {
    const url = 'https://randomuser.me/api/?results=10&inc=name';
    fetch(url)
      .then((res) => res.json())
      .then((json) => populateNames(json));
  }

  return {
    init() {
      fetchNames();
      return select;
    },

    getValue() {
      return select.value;
    },
  };
}
```

<div id="dynamic-input-custom-field-with-a-button-to-add-more-fields">
  ### フィールドを追加できる (+) ボタン付きの動的入力カスタムフィールド
</div>

ユーザーがフィールドをさらに追加できるカスタムフィールドです。

<Frame>
  <img src="https://mintcdn.com/translations/c0RQ9V0YAcT0-8l5/docs/images/cdy7uua7fh8z/7xM41qqb1zYjLAPG16wxGc/a33a3dd624222643e3f967ff35acbbac/Screenshot_2024-09-12_at_09.32.35.png?fit=max&auto=format&n=c0RQ9V0YAcT0-8l5&q=85&s=60099231db9f4e90097cd87a61e055d6" alt="" width="381" height="330" data-path="docs/images/cdy7uua7fh8z/7xM41qqb1zYjLAPG16wxGc/a33a3dd624222643e3f967ff35acbbac/Screenshot_2024-09-12_at_09.32.35.png" />
</Frame>

**ソースコード**:

```javascript lines expandable theme={null}
function DynamicInputs(context) {
  const DEFAULT_INITIAL_INPUTS = 2;
  const DEFAULT_PLACEHOLDER = 'jane.doe@example.com';
  const DEFAULT_ADD_BUTTON_TEXT = 'Add new item';
  const DEFAULT_INPUT_TYPE = 'email';
  const STATE_VALUE = {};
  const FIELD_ID = context.custom.createUid();
  let UUID_COUNTER = 0;
  let INPUTS_COUNTER = 0;

  const container = document.createElement('div');

  const inputsContainer = document.createElement('div');
  container.appendChild(inputsContainer);

  function buildAddNewItem() {
    const config = context.custom.getParams();
    const { add_button_text } = config;

    const ADD_BUTTON_TEXT = add_button_text || DEFAULT_ADD_BUTTON_TEXT;

    const addInputButton = document.createElement('button');
    addInputButton.type = 'button';
    addInputButton.classList.add('af-dynamic-input-add-button');
    addInputButton.id = `${FIELD_ID}_add-input-button`;
    addInputButton.onclick = buildInputContainer.bind(this);

    const addInputButtonIcon = document.createElement('span');
    addInputButtonIcon.classList.add('af-button', 'af-dynamic-input-add-button-icon');
    addInputButtonIcon.innerText = '+';

    const addInputButtonText = document.createElement('span');
    addInputButtonText.classList.add('af-dynamic-input-add-button-text');
    addInputButtonText.innerText = ADD_BUTTON_TEXT;

    addInputButton.appendChild(addInputButtonIcon);
    addInputButton.appendChild(addInputButtonText);
    container.appendChild(addInputButton);
  }

  function removeInput(container, input) {
    delete STATE_VALUE[input.name];
    container.remove();
  }

  function buildRemoveInputButton(container, input) {
    const button = document.createElement('button');
    button.type = 'button';
    button.classList.add('af-button', 'af-dynamic-input-remove-button');
    button.innerText = '-';
    button.onclick = removeInput.bind(this, container, input);

    INPUTS_COUNTER--;

    return button;
  }

  function buildInput() {
    const config = context.custom.getParams();
    const { placeholder, input_type } = config;

    const PLACEHOLDER = placeholder || DEFAULT_PLACEHOLDER;
    const INPUT_TYPE = input_type || DEFAULT_INPUT_TYPE;

    const input = document.createElement('input');
    input.type = INPUT_TYPE;
    input.placeholder = PLACEHOLDER;
    input.classList.add('af-stringField-input');
    input.name = `${FIELD_ID}_${UUID_COUNTER}`;
    input.id = input.name;
    input.addEventListener('change', () => {
      STATE_VALUE[input.name] = input.value;
    });

    UUID_COUNTER++;

    return input;
  }

  function buildInputContainer() {
    const container = document.createElement('div');
    container.classList.add('af-dynamic-input-container');

    const input = buildInput();
    container.appendChild(input);

    const removeButton = buildRemoveInputButton(container, input);
    container.appendChild(removeButton);

    inputsContainer.appendChild(container);

    INPUTS_COUNTER++;
  }

  function initComponent() {
    const config = context.custom.getParams();
    const { initial_inputs } = config;

    const INITIAL_INPUTS = initial_inputs || DEFAULT_INITIAL_INPUTS;
    INPUTS_COUNTER = INITIAL_INPUTS

    for (let i = 0; i < INITIAL_INPUTS; i++) {
      buildInputContainer();
    }
  }

  function blockFields(value) {
    const inputKeys = Object.keys(STATE_VALUE);

    inputKeys.forEach((o) => {
      const selector = document.getElementById(o);
      selector.disabled = value;
    });
  }

  return {
    init() {
      buildAddNewItem();
      initComponent();
      return container;
    },

    block() {
      blockFields(true);
    },

    unblock() {
      blockFields(false);
    },

    getValue() {
      return Object.values(STATE_VALUE);
    },
  };
}
```

**CSSコード：**

```css lines expandable theme={null}
.af-button.af-dynamic-input-remove-button {
  width: 48px;
  color: var(--button-font-color);
  background: var(--button-background-color);
}

.af-dynamic-input-container {
  display: flex;
  margin-bottom: var(--spacing-1);
}

.af-dynamic-input-container input {
  margin-right: var(--spacing-1);
}

button.af-dynamic-input-add-button {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  margin-top: var(--spacing-1);
  display: inline-flex;
  cursor: pointer;
  align-items: center;
}

.af-button.af-dynamic-input-add-button-icon {
  background: var(--primary-color);
  width: 24px;
  padding: 0;
  height: 24px;
  border-radius: .3em;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
  margin-right: var(--spacing-1);
}

.af-dynamic-input-add-button-text {
  color: var(--label-font-color);
  font-size: var(--label-font-size);
}

.af-dynamic-input-add-button:focus {
  outline: none;
}

.af-dynamic-input-add-button:hover .af-button {
  transition: filter var(--transition-normal), box-shadow var(--transition-normal);
  filter: brightness(1.1);
  box-shadow: 0 0 0 var(--outline-width) var(--outline-color), 0px 4px 8px -4px var(--shadow-color), 0px 16px 24px var(--shadow-color);
}

.af-dynamic-input-add-button:focus .af-button {
  box-shadow: 0 0 0 var(--outline-width) var(--outline-color), 0px 4px 8px -4px var(--shadow-color), 0px 16px 24px var(--shadow-color);
}
```
