body method

  1. @override
String body(
  1. String baseName,
  2. String className
)
override

Defines the actual body code. path is passed relative to lib, baseName is the filename, and className is the filename converted to Pascal case.

実際の本体コードを定義します。pathlibからの相対パス、baseNameにファイル名が渡され、classNameにファイル名をパスカルケースに変換した値が渡されます。

Implementation

@override
String body(String baseName, String className) {
  return """
`FormBuilder`は下記のように利用する。

## 概要

$excerpt

## パッケージのインポート

このコンポーネントを使用するには、以下のパッケージをインポートする必要があります:

```dart
import 'package:masamune/masamune.dart';
```

このインポートにより、Masamuneフレームワークが提供するすべてのフォームコンポーネントとユーティリティにアクセスできます。

## 配置方法

`FormController`を使用する場合は、`FormController.key`を与えた`Form`配下に配置するか、`form`パラメータに`FormController`を渡します。

```dart
final formController = FormController();

// パターン1: Formの配下に配置
Form(
key: formController.key,
child: Column(
  children: [
    FormBuilder(
      initialValue: formController.value.type,
      onSaved: (value) => formController.value.copyWith(type: value),
      builder: (context, ref, item) {
        // ...
      },
    ),
  ],
),
);

// パターン2: formパラメータに直接渡す
FormBuilder(
form: formController,
initialValue: formController.value.type,
onSaved: (value) => formController.value.copyWith(type: value),
builder: (context, ref, item) {
  // ...
},
);
```

## 基本的な利用方法

```dart
FormBuilder(
form: formController,
initialValue: formController.value.type,
onSaved: (value) => formController.value.copyWith(type: value),
builder: (context, ref, item) {
  return Row(
    children: [
      FilledButton(
        onPressed: item == UserType.admin ? null : () {
          ref.update(UserType.admin);
        },
        child: const Text("管理者"),
      ),
      const SizedBox(width: 16),
      FilledButton(
        onPressed: item == UserType.user ? null : () {
          ref.update(UserType.user);
        },
        child: const Text("一般ユーザー"),
      ),
      const SizedBox(width: 16),
      FilledButton(
        onPressed: item == UserType.guest ? null : () {
          ref.update(UserType.guest);
        },
        child: const Text("ゲスト"),
      ),
    ],
  );
},
);
```

## `FormController`を使用しない場合の利用方法

```dart
FormBuilder(
initialValue: UserType.admin,
onChanged: (value) {
  print(value);
},
builder: (context, ref, item) {
  return Row(
    children: [
      FilledButton(
        onPressed: item == UserType.admin ? null : () {
          ref.update(UserType.admin);
        },
        child: const Text("管理者"),
      ),
      const SizedBox(width: 16),
      FilledButton(
        onPressed: item == UserType.user ? null : () {
          ref.update(UserType.user);
        },
        child: const Text("一般ユーザー"),
      ),
      const SizedBox(width: 16),
      FilledButton(
        onPressed: item == UserType.guest ? null : () {
          ref.update(UserType.guest);
        },
        child: const Text("ゲスト"),
      ),
    ],
  );
},
);
```

## モーダルを利用したフォームの構築

```dart
FormBuilder(
form: formController,
onSaved: (value) => formController.value.copyWith(type: value),
initialValue: formController.value.type,
builder: (context, ref, item) {
  return FilledButton(
    onPressed: () async {
      final res = await showModalBottomSheet(
        context: context,
        builder: (context) {
          return FormEnumModalField(
            initialValue: formController.value.type,
            onChanged: (value) {
              Navigator.pop(context, value);
            },
            picker: FormEnumModalFieldPicker(
              values: UserType.values,
            ),
          );
        },
      );
      if (res != null) {
        ref.update(res);
      }
    },
    child: const Text("モーダルを表示して選択"),
  );
},
);
```

## バリデーション状態の監視

```dart
FormBuilder(
form: formController,
onSaved: (value) => formController.value.copyWith(type: value),
initialValue: formController.value.type,
validator: (value) {
  if (value == null) {
    return "ユーザータイプを選択してください";
  }
  return null;
},
builder: (context, ref, item) {
  return Row(
    children: [
      FilledButton(
        onPressed: item == UserType.admin ? null : () {
          ref.update(UserType.admin);
        },
        child: const Text("管理者"),
      ),
      const SizedBox(width: 16),
      FilledButton(
        onPressed: item == UserType.user ? null : () {
          ref.update(UserType.user);
        },
        child: const Text("一般ユーザー"),
      ),
      const SizedBox(width: 16),
      FilledButton(
        onPressed: item == UserType.guest ? null : () {
          ref.update(UserType.guest);
        },
        child: const Text("ゲスト"),
      ),
    ],
  );
},
);
```

## カスタムデザインの適用

```dart
FormBuilder(
form: formController,
onSaved: (value) => formController.value.copyWith(type: value),
initialValue: formController.value.type,
style: const FormStyle(
  padding: EdgeInsets.all(16.0),
  backgroundColor: Colors.grey[100],
  borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
builder: (context, ref, item) {
  return Column(
    children: [
      FilledButton(
        onPressed: item == UserType.admin ? null : () {
          ref.update(UserType.admin);
        },
        child: const Text("管理者"),
      ),
      const SizedBox(width: 16),
      FilledButton(
        onPressed: item == UserType.user ? null : () {
          ref.update(UserType.user);
        },
        child: const Text("一般ユーザー"),
      ),
      const SizedBox(width: 16),
      FilledButton(
        onPressed: item == UserType.guest ? null : () {
          ref.update(UserType.guest);
        },
        child: const Text("ゲスト"),
      ),
    ],
  );
},
);
```

## パラメータ

### 必須パラメータ
- `builder`: ビルダー関数。フォームの構造を動的に生成します。

### オプションパラメータ
- `form`: フォームコントローラー。フォームの状態管理を行います。定義する場合は`onSaved`パラメータも定義する必要があります。
- `onSaved`: 保存時のコールバック。選択された値の保存処理を定義します。定義する場合は`form`パラメータも定義する必要があります。
- `onChanged`: 変更時のコールバック。選択された値の変更時の処理を定義します。
- `style`: フォームのスタイル。`FormStyle`を使用してデザインをカスタマイズできます。
- `validator`: バリデーション関数。選択値の検証ルールを定義します。
- `enabled`: 入力可否。`false`の場合、フォームが無効化されます。
- `initialValue`: 初期値。フォーム表示時の初期チェック状態を設定します。
- `labelText`: ラベルテキスト。フォームのラベルを設定します。
- `keepAlive`: リストに配置された場合、スクロール時に破棄されないようにするかどうか。`true`の場合、破棄されず保持され続けます。デフォルトは`true`です。

## 注意点

- `FormController`を使用する場合は、`FormController.key`を与えた`Form`配下に配置するか、`form`パラメータに`FormController`を渡す必要があります。
- `FormController`と組み合わせて使用することで、フォームの状態管理を行えます。
- `FormController`を使用する場合は`onSaved`メソッドも合わせて定義してください。
- `form`と`onSaved`はセットで使用する必要があります。どちらか一方だけを定義するとエラーになります。
- `FormStyle`を使用することで、共通のデザインを適用できます。
- ビルダー関数内で自由にフォーム作成することができます。
- リスト内で使用する場合、`keepAlive`を`true`にすることで、スクロール時にフォームの状態が保持されます。

## ベストプラクティス

1. フォームの状態管理には`FormController`を使用する
2. `FormController`を使用する場合は、必ず`form`と`onSaved`をセットで定義する
3. `FormController.key`を与えた`Form`配下に配置するか、`form`パラメータに`FormController`を渡すことで配置する
4. `FormController`を使用せず、`onChanged`メソッドを使用して変更の都度処理を行う方法も利用可能
5. バリデーションは`validator`パラメータを使用して定義する
6. アプリ全体で統一したデザインを適用するために`FormStyle`を使用する
7. リスト内で使用する場合は`keepAlive`を`true`に設定して状態を保持する(デフォルトで`true`)

## 利用シーン

- 複雑なフォームの構築
- 条件付きフォームフィールドの表示
- ステップ形式のフォーム
- 動的なフォームレイアウト
- フォームの状態に応じたUI更新
""";
}