Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add manual discriminator mode #3

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/utils/src/schema/getClosestMatchingOption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import retrieveSchema from './retrieveSchema';
import { ONE_OF_KEY, REF_KEY } from '../constants';
import guessType from '../guessType';
import { FormContextType, RJSFSchema, StrictRJSFSchema, ValidatorType } from '../types';
import { getOptionMatchingManualDiscriminator } from 'schema/getOptionMatchingManualDiscriminator';

/** A junk option used to determine when the getFirstMatchingOption call really matches an option rather than returning
* the first item
Expand Down Expand Up @@ -131,6 +132,11 @@ export default function getClosestMatchingOption<
selectedOption = -1,
discriminatorField?: string
): number {
const manualDiscriminatorMatch = getOptionMatchingManualDiscriminator(discriminatorField, formData, options);
if (manualDiscriminatorMatch !== undefined) {
return manualDiscriminatorMatch;
}

// Reduce the array of options down to a list of the indexes that are considered matching options
const allValidIndexes = options.reduce((validList: number[], option, index: number) => {
const testOptions: S[] = [JUNK_OPTION as S, option];
Expand Down
7 changes: 7 additions & 0 deletions packages/utils/src/schema/getMatchingOption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import has from 'lodash/has';

import { PROPERTIES_KEY } from '../constants';
import { FormContextType, RJSFSchema, StrictRJSFSchema, ValidatorType } from '../types';
import { getOptionMatchingManualDiscriminator } from 'schema/getOptionMatchingManualDiscriminator';

/** Given the `formData` and list of `options`, attempts to find the index of the option that best matches the data.
* Deprecated, use `getFirstMatchingOption()` instead.
Expand Down Expand Up @@ -32,6 +33,12 @@ export default function getMatchingOption<
if (formData === undefined) {
return 0;
}

const manualDiscriminatorMatch = getOptionMatchingManualDiscriminator(discriminatorField, formData, options);
if (manualDiscriminatorMatch !== undefined) {
return manualDiscriminatorMatch;
}

Comment on lines +36 to +41

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation already exists on lines 46-51. Are you trying to avoid the isValid check?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is exactly what I am doing - this makes all the difference between a fast vs. an unusably sluggish form in my use-case :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if the PR fix will help your use case once we release it?

for (let i = 0; i < options.length; i++) {
const option = options[i];

Expand Down
23 changes: 23 additions & 0 deletions packages/utils/src/schema/getOptionMatchingManualDiscriminator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import get from 'lodash/get';
import { PROPERTIES_KEY } from '../constants';

export const getOptionMatchingManualDiscriminator = (
discriminatorField: string | undefined,
formData: any,
options: object[]
): number | undefined | void => {
if (!discriminatorField || !formData) {
return;
}

const value = get(formData, discriminatorField);

for (let i = 0; i < options.length; i++) {
const option = options[i];
const discriminator = get(option, [PROPERTIES_KEY, discriminatorField], {});

if (discriminator?.enum?.includes(value)) {
return i;
}
}
};