convert params form to all signals

This commit is contained in:
Joel Wetzell
2026-04-04 08:47:43 -05:00
parent c25b3b83aa
commit d12857ef2f
2 changed files with 44 additions and 46 deletions
@@ -1,4 +1,4 @@
@if (paramsSchema && paramsFormInfo) { @if (paramsSchema() && paramsFormInfo) {
<form [formGroup]="paramsFormInfo.formGroup"> <form [formGroup]="paramsFormInfo.formGroup">
<div class="flex flex-col"> <div class="flex flex-col">
@for (key of paramKeys(); track key) { @for (key of paramKeys(); track key) {
+43 -45
View File
@@ -1,5 +1,11 @@
import { JsonPipe } from '@angular/common'; import { JsonPipe } from '@angular/common';
import { Component, inject, Input, OnChanges, OnDestroy, OnInit, output, SimpleChange, SimpleChanges } from '@angular/core'; import {
Component,
effect,
input,
OnDestroy,
output
} from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms'; import { ReactiveFormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
@@ -7,10 +13,9 @@ import { MatInputModule } from '@angular/material/input';
import { MatTabsModule } from '@angular/material/tabs'; import { MatTabsModule } from '@angular/material/tabs';
import { MatTooltipModule } from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip';
import { SomeJSONSchema } from 'ajv/dist/types/json-schema'; import { SomeJSONSchema } from 'ajv/dist/types/json-schema';
import { cloneDeep, has, isEqual } from 'lodash-es'; import { cloneDeep, has } from 'lodash-es';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { ParamInfo, ParamsFormInfo } from '../../models/form'; import { ParamInfo, ParamsFormInfo } from '../../models/form';
import { SchemaService } from '../../services/schema';
import { cleanParams, schemaToParamsFormInfo } from '../../utils/params'; import { cleanParams, schemaToParamsFormInfo } from '../../utils/params';
import { ArrayFormComponent } from '../array-form/array-form'; import { ArrayFormComponent } from '../array-form/array-form';
@Component({ @Component({
@@ -29,48 +34,41 @@ import { ArrayFormComponent } from '../array-form/array-form';
], ],
standalone: true, standalone: true,
}) })
export class ParamsFormComponent implements OnChanges, OnDestroy { export class ParamsFormComponent implements OnDestroy {
@Input() paramsSchema?: SomeJSONSchema; data = input<any>();
@Input() data?: any; paramsSchema = input<SomeJSONSchema>();
updated = output<any>(); updated = output<any>();
paramsFormInfo?: ParamsFormInfo; paramsFormInfo?: ParamsFormInfo;
formGroupSubscription?: Subscription; formGroupSubscription?: Subscription;
constructor() {
ngOnDestroy(): void { // TODO(jwetzell): do this in a bit more of a standard signal way
if (this.formGroupSubscription) { effect(() => {
this.formGroupSubscription.unsubscribe() const schema = this.paramsSchema();
} if (schema !== undefined) {
} if (schema.properties) {
this.paramsFormInfo = schemaToParamsFormInfo(schema);
ngOnChanges(changes: SimpleChanges<{ if (this.formGroupSubscription === undefined) {
paramsSchema: SomeJSONSchema this.formGroupSubscription = this.paramsFormInfo?.formGroup.valueChanges.subscribe(
data: any () => {
}>): void {
if (changes.paramsSchema) {
if (changes.paramsSchema.previousValue === undefined && changes.paramsSchema.currentValue !== undefined) {
if (this.paramsSchema) {
if (this.paramsSchema.properties) {
this.paramsFormInfo = schemaToParamsFormInfo(this.paramsSchema);
if (this.formGroupSubscription === undefined) {
this.formGroupSubscription = this.paramsFormInfo?.formGroup.valueChanges.subscribe((value) => {
this.formUpdated(); this.formUpdated();
}); },
} );
} else {
console.error('params is not a singular object');
console.error(this.paramsSchema);
} }
} else {
console.error('params is not a singular object');
console.error(schema);
} }
} }
} });
if (changes.data) { effect(() => {
if (!isEqual(changes.data.currentValue, changes.data.previousValue)) { const dataToPatch = cloneDeep(this.data());
if (this.paramsSchema() && this.paramsFormInfo && dataToPatch) {
if (this.paramsFormInfo?.formGroup !== undefined) { if (this.paramsFormInfo?.formGroup !== undefined) {
// NOTE(jwetzell): prepare data for form patching // NOTE(jwetzell): prepare data for form patching
const dataToPatch = cloneDeep(this.data); // const dataToPatch = cloneDeep(this.data);
Object.entries(this.paramsFormInfo.paramsInfo).forEach(([paramKey, paramInfo]) => { Object.entries(this.paramsFormInfo.paramsInfo).forEach(([paramKey, paramInfo]) => {
if (has(dataToPatch, paramKey)) { if (has(dataToPatch, paramKey)) {
switch (paramInfo.type) { switch (paramInfo.type) {
@@ -98,15 +96,19 @@ export class ParamsFormComponent implements OnChanges, OnDestroy {
this.paramsFormInfo.formGroup.patchValue(dataToPatch); this.paramsFormInfo.formGroup.patchValue(dataToPatch);
} }
} }
});
}
ngOnDestroy(): void {
if (this.formGroupSubscription) {
this.formGroupSubscription.unsubscribe();
} }
} }
formUpdated() { formUpdated() {
if (this.paramsSchema) { const paramsSchema = this.paramsSchema();
const params = cleanParams( if (paramsSchema) {
this.paramsSchema, const params = cleanParams(paramsSchema, this.paramsFormInfo?.formGroup.value);
this.paramsFormInfo?.formGroup.value,
);
this.updated.emit(params); this.updated.emit(params);
} else { } else {
console.error('params-form: no paramsSchema loaded'); console.error('params-form: no paramsSchema loaded');
@@ -125,14 +127,10 @@ export class ParamsFormComponent implements OnChanges, OnDestroy {
} }
getParamValue(key: string) { getParamValue(key: string) {
if (this.paramsSchema) { const paramsSchema = this.paramsSchema();
const params = cleanParams( if (paramsSchema) {
this.paramsSchema, const params = cleanParams(paramsSchema, this.paramsFormInfo?.formGroup.value);
this.paramsFormInfo?.formGroup.value,
);
return params[key]; return params[key];
} }
} }
} }