Enable dynamic schema composition based on form state
- 主要言語
- 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