Skip to content

Commit

Permalink
feat: add touched and dirty helpers (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
timdeschryver authored Jan 27, 2024
1 parent d03d875 commit 4479d9b
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 40 deletions.
10 changes: 9 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@
"extends": ["plugin:@nx/typescript"],
"rules": {
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/no-explicit-any": "off"
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_"
}
]
}
},
{
Expand Down
4 changes: 2 additions & 2 deletions apps/example/src/app/custom-input-error.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import { injectErrorField } from '@ng-signal-forms';
standalone: true,
imports: [NgIf, NgFor, JsonPipe],
template: `
<div *ngIf="touchedState() === 'TOUCHED'">
<div *ngIf="touched()">
<p *ngFor="let message of errorMessages()">{{ message }}</p>
</div>
`,
})
export class CustomErrorComponent {
private _formField = injectErrorField();
public touchedState = this._formField.touchedState;
public touched = this._formField.touched;
public errors = this._formField.errors;

public errorMessages = computed(() =>
Expand Down
24 changes: 15 additions & 9 deletions packages/platform/src/lib/form-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ export type FormField<Value = unknown> = {
state: Signal<ValidationState>;
valid: Signal<boolean>;
dirtyState: Signal<DirtyState>;
dirty: Signal<boolean>;
touchedState: Signal<TouchedState>;
touched: Signal<boolean>;
hidden: Signal<boolean>;
disabled: Signal<boolean>;
markAsTouched: () => void;
Expand Down Expand Up @@ -72,15 +74,17 @@ export function createFormField<Value>(
const stateSignal = computeState(validateStateSignal);
const validSignal = computed(() => stateSignal() === 'VALID');

const touchedSignal = signal<TouchedState>('UNTOUCHED');
const dirtySignal = signal<DirtyState>('PRISTINE');
const touchedStateSignal = signal<TouchedState>('UNTOUCHED');
const touchedSignal = computed(() => touchedStateSignal() === 'TOUCHED');
const dirtyStateSignal = signal<DirtyState>('PRISTINE');
const dirtySignal = computed(() => dirtyStateSignal() === 'DIRTY');
const hiddenSignal = signal(false);
const disabledSignal = signal(false);

effect(
() => {
if (valueSignal()) {
dirtySignal.set('DIRTY');
dirtyStateSignal.set('DIRTY');
}
},
{
Expand Down Expand Up @@ -124,17 +128,19 @@ export function createFormField<Value>(
errorsArray: errorsArraySignal,
state: stateSignal,
valid: validSignal,
touchedState: touchedSignal,
dirtyState: dirtySignal,
touchedState: touchedStateSignal,
touched: touchedSignal,
dirtyState: dirtyStateSignal,
dirty: dirtySignal,
hidden: hiddenSignal,
disabled: disabledSignal,
markAsTouched: () => touchedSignal.set('TOUCHED'),
markAsDirty: () => dirtySignal.set('DIRTY'),
markAsTouched: () => touchedStateSignal.set('TOUCHED'),
markAsDirty: () => dirtyStateSignal.set('DIRTY'),
registerOnReset: (fn: (value: Value) => void) => (onReset = fn),
reset: () => {
valueSignal.set(defaultValue);
touchedSignal.set('UNTOUCHED');
dirtySignal.set('PRISTINE');
touchedStateSignal.set('UNTOUCHED');
dirtyStateSignal.set('PRISTINE');
onReset(defaultValue);
},
};
Expand Down
66 changes: 38 additions & 28 deletions packages/platform/src/lib/form-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ export type FormGroup<Fields extends FormGroupCreatorOrSignal = {}> = {
valid: Signal<boolean>;
state: Signal<ValidationState>;
dirtyState: Signal<DirtyState>;
dirty: Signal<boolean>;
touchedState: Signal<TouchedState>;
touched: Signal<boolean>;
errors: Signal<{}>;
errorsArray: Signal<InvalidDetails[]>;
markAllAsTouched: () => void;
Expand Down Expand Up @@ -117,6 +119,38 @@ export function createFormGroup<FormFields extends FormGroupCreator>(
return 'VALID';
});

const dirtyStateSignal = computed(() => {
const fg = isSignal(formFieldsMapOrSignal)
? formFieldsMapOrSignal()
: formFieldsMapOrSignal;

const states = Object.values(fg).map((f) => f.dirtyState());

const isDirty = states.some((e) => e === 'DIRTY');
if (isDirty) {
return 'DIRTY';
}

return 'PRISTINE';
})
const dirtySignal = computed(() => dirtyStateSignal() === 'DIRTY');

const touchedStateSignal = computed(() => {
const fg = isSignal(formFieldsMapOrSignal)
? formFieldsMapOrSignal()
: formFieldsMapOrSignal;

const states = Object.values(fg).map((f) => f.touchedState());

const isTouched = states.some((e) => e === 'TOUCHED');
if (isTouched) {
return 'TOUCHED';
}

return 'UNTOUCHED';
})
const touchedSignal = computed(() => touchedStateSignal() === 'TOUCHED');

return {
__type: 'FormGroup',
value: valueSignal,
Expand All @@ -138,34 +172,10 @@ export function createFormGroup<FormFields extends FormGroupCreator>(
});
return myErrors.concat(...childErrors);
}),
dirtyState: computed(() => {
const fg = isSignal(formFieldsMapOrSignal)
? formFieldsMapOrSignal()
: formFieldsMapOrSignal;

const states = Object.values(fg).map((f) => f.dirtyState());

const isDirty = states.some((e) => e === 'DIRTY');
if (isDirty) {
return 'DIRTY';
}

return 'PRISTINE';
}),
touchedState: computed(() => {
const fg = isSignal(formFieldsMapOrSignal)
? formFieldsMapOrSignal()
: formFieldsMapOrSignal;

const states = Object.values(fg).map((f) => f.touchedState());

const isTouched = states.some((e) => e === 'TOUCHED');
if (isTouched) {
return 'TOUCHED';
}

return 'UNTOUCHED';
}),
dirtyState: dirtyStateSignal,
dirty: dirtySignal,
touchedState: touchedStateSignal,
touched: touchedSignal,
markAllAsTouched: () => {
const fg = isSignal(formFieldsMapOrSignal)
? formFieldsMapOrSignal()
Expand Down

0 comments on commit 4479d9b

Please sign in to comment.