-
Notifications
You must be signed in to change notification settings - Fork 33
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
refactor(oneOf validator): Refactor oneOf validator #95
base: feat/formgroup-validator-oneof
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { AbstractControl } from '@angular/forms'; | ||
import { TypedFormGroup, TypedValidatorFn } from './ngx-sub-form.types'; | ||
import { | ||
isNullOrUndefined, | ||
OneOfValidatorRequiresMoreThanOneFieldError, | ||
OneOfValidatorUnknownFieldError, | ||
} from './ngx-sub-form-utils'; | ||
|
||
export namespace NgxSubFormValidators { | ||
|
||
export function oneOf<FormInterface>(keysArray: Array<keyof FormInterface>, errorKey = 'oneOf'): TypedValidatorFn<FormInterface> { | ||
if (!keysArray || keysArray.length < 2) { | ||
throw new OneOfValidatorRequiresMoreThanOneFieldError(); | ||
} | ||
|
||
return (formGroup: TypedFormGroup<FormInterface>) => { | ||
|
||
const notNullKeys: Array<keyof FormInterface> = keysArray.filter((key) => { | ||
const control: AbstractControl | null = formGroup.get(key as string); | ||
|
||
if (!control) { | ||
throw new OneOfValidatorUnknownFieldError(key as string); | ||
} | ||
|
||
return !isNullOrUndefined(control.value); | ||
}); | ||
|
||
if (notNullKeys.length === 1) { | ||
return null; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't take into account if multiple properties are defined. From the example above, if That error should be optional when I think about it, and turned on by default. But I believe that by default we should have an error if more than one value is defined with a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mentioned this in the other PR but I’m not getting what you mean? This code works and passes the unit tests? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From the example above, if assassinDroid AND medicalDroid are defined, notNullKeys.length is 2, not 1; there will be an error |
||
|
||
return { [errorKey]: notNullKeys }; | ||
} | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you want to be able to change the error key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh nvm I just saw why:
NgxSubFormValidators.oneOf(['allianceRebel', 'allianceImperial'], 'oneOfAllianceType')
Few things here, the key should probably be at the beginning (just a preference) but something that might lead to weird results:
When using 2
oneOf
(or more), as the key is optional it would override the previous result if someone forgets to pass it.I think it'd probably be better to have the definition of
oneOf
to be :This way, we only need to use
oneOf
once, it'll loop over the properties of the form once too (not X times where X is the number of times you calloneOf
)Also, in the above we'd be using as key what's defined in the original object and mapping that to keys of the sub form
The above doesn't fully work though...
I get
Type 'string[]' is not assignable to type 'FormInterface'
but that should be doable :)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intent here, and what I’m optimising for is the common case. It strikes me as incredibly rare that you’d want to have multiple oneOfs in a single form, so I think we should not be making the api awkward for that one case.
I was also struggling with the problem of the error clobbering if you forgot to set the key name for differentiation, but I think you’ve got a great idea with having the argument be an object. However, I think we should support both options simultaneously, again to avoid an awkward interface for the extremely rare case. This could be handled by just checking if the first arg is array or object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another possibly simpler option is to have NgxSubFormValidators.oneOf and NgxSubFormValidators.oneOfMultiple