angular / angular/angular

Enable dynamic schema composition based on form state

オープン
#67,071 コメント 4 件 リアクション 3 件 担当者 0 名 GitHub で見る
area: forms forms: signals
主要言語
TypeScript
スター
101k
フォーク
27.5k
平均マージ
1日 19時間
マージ済み PR(30日)
288

説明

### Which @angular/* package(s) are relevant/related to the feature request?

_No response_

---

### Description

I have a form with different properties.

```ts
export interface Field {
fieldName: string;
fieldType?: string;
fieldRequired?: boolean;
fieldMaxSize?: number;
fieldVisible?: boolean;
}

export interface FieldConfig {
fields: Field[];
}

export interface Order {
label: string;
// ...
}

export interface ActivityType {
label: string;
fieldConfig: FieldConfig;
}

export function fieldConfigSchema(fieldConfig: FieldConfig) {
return schema(path => {
for (const field of fieldConfig.fields) {
required(path[field.fieldName], { when: () => field.fieldRequired });
hidden(path[field.fieldName], () => !field.fieldVisible);
maxLength(path[field.fieldName], () => field.fieldMaxSize);
}
});
}

export interface FormModel {
user: User;
activityType: ActivityType;
order: Order;
}
```

The form is defined as follows:

```ts
formModel = signal({
user: null,
activityType: null,
order: null
});

form = form(this.formModel, path => {
applyWhen(
path.order,
context => !!context.valueOf(path.activityType)?.fieldConfig,
fieldConfigSchema(
/* value of fieldConfig from activityType not available here */
)
);
});
```

The issue is that `fieldConfigSchema` needs access to the `fieldConfig`
coming from the selected `activityType`, but that value is only available
through the form context.

---

### Proposed solution

Allow building a schema dynamically based on the form context:

```ts
applyWhen(
path.order,
context => !!context.valueOf(path.activityType)?.fieldConfig,
context =>
fieldConfigSchema(
context.valueOf(path.activityType).fieldConfig
)
);
```

This would allow the schema to be constructed using runtime values from
the form context.

---

### Alternatives considered

```ts
export function fieldConfigSchema(fieldConfig: Signal) {
return schema(path => {
for (const field of fieldConfig().fields) {
required(path[field.fieldName], { when: () => field.fieldRequired });
hidden(path[field.fieldName], () => !field.fieldVisible);
maxLength(path[field.fieldName], () => field.fieldMaxSize);
}
});
}

form = form(this.formModel, path => {
applyWhen(
path.order,
context => !!context.valueOf(path.activityType)?.fieldConfig,
fieldConfigSchema(this.fieldConfig)
);
});
fieldConfig = computed(() => this.form.activityType().value()?.fieldConfig);
```

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

まず、form、applyWhen、schema、context.valueOf APIを追跡して、現在スキーマがどのように構築され、いつformコンテキストが利用可能になるのかを理解します。activityType fieldConfigの例をカバーし、既存の動作を維持したうえで、実行時のformコンテキストからスキーマを構築できれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
angular, typescript
領域
frontend
issue の種類
機能追加
難易度
5/5
見積もり時間
1週間以上
活発さ
静か
明瞭さ
おおむね明確
初心者へのやさしさ
35/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。