Skip to content

Commit

Permalink
parent form should trigger subform validate event (#2820)
Browse files Browse the repository at this point in the history
Co-authored-by: hoppe <hoppewang@microsoft.com>
  • Loading branch information
wanghoppe and hoppe committed Oct 24, 2023
1 parent f98e158 commit 54a9e5e
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 41 deletions.
27 changes: 27 additions & 0 deletions packages/bonito-core/src/form/__tests__/form.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,33 @@ describe("Form tests", () => {
expect(validationStatus).toBe(form.validationStatus);
});

test("Subform validate event", async () => {
type HelloWorldFormValues = {
message: string;
};

const form = createForm<HelloWorldFormValues>({
values: {
message: "Hello world!",
},
});

const parentForm = createForm({
values: {
child: {},
},
});

parentForm.subForm("child", form);

const validateSpy = jest.fn();
form.on("validate", validateSpy);
parentForm.validate();
expect(validateSpy).toHaveBeenCalled();
await parentForm.waitForValidation();
expect(validateSpy).toHaveBeenCalledTimes(2);
});

test("Events", () => {
type ElfType = {
name: string;
Expand Down
18 changes: 0 additions & 18 deletions packages/bonito-core/src/form/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,24 +129,6 @@ export interface Form<V extends FormValues> {
*/
validate(opts?: ValidationOpts): Promise<ValidationSnapshot<V>>;

/**
* Perform synchronous validation
* @param opts Validation options
*/
validateSync(
snapshot: ValidationSnapshot<V>,
opts: ValidationOpts
): ValidationSnapshot<V>;

/**
* Perform asynchronous validation
* @param opts Validation options
*/
validateAsync(
snapshot: ValidationSnapshot<V>,
opts: ValidationOpts
): Promise<ValidationSnapshot<V>>;

/**
* Returns a promise that resolves when any current form validation is
* finished. If there is no validation in progress, returns a promise which
Expand Down
50 changes: 29 additions & 21 deletions packages/bonito-core/src/form/internal/form-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,6 @@ export class FormImpl<V extends FormValues> implements Form<V> {
this._validationSnapshot = snapshot;
this.validateSync(snapshot, opts);

// Fire a validation event to allow updates after synchronous
// validation to happen immediately
this._emitValidateEvent(snapshot);

// Yield before doing any async validation to check if another validation
// attempt has come in.
let delayMs = 0;
Expand All @@ -320,26 +316,13 @@ export class FormImpl<V extends FormValues> implements Form<V> {

await this.validateAsync(snapshot, opts);

if (this._checkAndCancelValidationSnapshot(snapshot, opts.force)) {
return snapshot;
}

// This snapshot is done, and is now the current in-effect snapshot
snapshot.validationCompleteDeferred.resolve();
snapshot.updateOverallStatus();
this._validationSnapshot = snapshot;

this._emitValidateEvent(snapshot);

if (!snapshot.overallStatus) {
// Hitting this indicates a bug. This shouldn't ever be undefined
// at this point.
throw new Error("Failed to compute overall validation status");
}

return snapshot;
}

/**
* Perform synchronous validation
* @param opts Validation options
*/
validateSync(
snapshot: ValidationSnapshot<V>,
opts: ValidationOpts
Expand Down Expand Up @@ -373,9 +356,17 @@ export class FormImpl<V extends FormValues> implements Form<V> {

snapshot.syncValidationComplete = true;

// Fire a validation event to allow updates after synchronous
// validation to happen immediately
this._emitValidateEvent(snapshot);

return snapshot;
}

/**
* Perform asynchronous validation
* @param opts Validation options
*/
async validateAsync(
snapshot: ValidationSnapshot<V>,
opts: ValidationOpts
Expand Down Expand Up @@ -443,6 +434,23 @@ export class FormImpl<V extends FormValues> implements Form<V> {

snapshot.asyncValidationComplete = true;

if (this._checkAndCancelValidationSnapshot(snapshot, opts.force)) {
return snapshot;
}

// This snapshot is done, and is now the current in-effect snapshot
snapshot.validationCompleteDeferred.resolve();
snapshot.updateOverallStatus();
this._validationSnapshot = snapshot;

this._emitValidateEvent(snapshot);

if (!snapshot.overallStatus) {
// Hitting this indicates a bug. This shouldn't ever be undefined
// at this point.
throw new Error("Failed to compute overall validation status");
}

return snapshot;
}

Expand Down
4 changes: 2 additions & 2 deletions packages/bonito-core/src/form/subform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,14 @@ export class SubForm<
snapshot: ValidationSnapshot<S>,
opts: ValidationOpts
): ValidationSnapshot<S> {
return this.form.validateSync(snapshot, opts);
return (this.form as FormImpl<S>).validateSync(snapshot, opts);
}

async validateAsync(
snapshot: ValidationSnapshot<S>,
opts: ValidationOpts
): Promise<ValidationSnapshot<S>> {
return this.form.validateAsync(snapshot, opts);
return (this.form as FormImpl<S>).validateAsync(snapshot, opts);
}

forceValidationStatus(status: ValidationStatus): void {
Expand Down

0 comments on commit 54a9e5e

Please sign in to comment.