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

[BreakingChange] [Validators]: Refactor Fudis.atLeastOneRequired validator name to Fudis.oneRequired #438

Merged
merged 8 commits into from
Sep 18, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export class AppFormExampleComponent implements OnInit {
english: new FormControl<string | null>(null),
},
[
FudisGroupValidators.atLeastOneRequired(
FudisGroupValidators.oneRequired(
this._translocoService.selectTranslate('error_one_required'),
),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const testFormGroup = new FormGroup<FudisCheckboxGroupFormGroup<object>>(
pineapple: new FormControl<boolean | null | undefined>(null),
orange: new FormControl<boolean | null | undefined>(null),
},
[FudisGroupValidators.atLeastOneRequired(new BehaviorSubject('No fruit picked! :('))],
[FudisGroupValidators.oneRequired(new BehaviorSubject('No fruit picked! :('))],
);

type TestOption = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from '../../../types/forms';

import { FieldSetBaseDirective } from '../../../directives/form/fieldset-base/fieldset-base.directive';
import { hasAtLeastOneRequiredOrMinValidator } from '../../../utilities/form/getValidators';
import { hasOneRequiredOrMinValidator } from '../../../utilities/form/getValidators';
import { FormComponent } from '../form/form.component';
import { FudisIdService } from '../../../services/id/id.service';
import { FudisTranslationService } from '../../../services/translation/translation.service';
Expand All @@ -38,7 +38,7 @@ export class CheckboxGroupComponent extends FieldSetBaseDirective implements OnI

this._updateValueAndValidityTrigger.pipe(takeUntilDestroyed()).subscribe(() => {
if (this.formGroup) {
this._required = hasAtLeastOneRequiredOrMinValidator(this.formGroup);
this._required = hasOneRequiredOrMinValidator(this.formGroup);
}
});
}
Expand Down Expand Up @@ -99,7 +99,7 @@ export class CheckboxGroupComponent extends FieldSetBaseDirective implements OnI
/**
* Validation check can be currently be done only for App provided formGroup
*/
this._required = hasAtLeastOneRequiredOrMinValidator(this.formGroup);
this._required = hasOneRequiredOrMinValidator(this.formGroup);
}

this._initialCheck(this.formGroup);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ When Form Group has validation errors, the visual and screen reader attributes a

### As a Required Fieldset

To mark Checkbox Group as Required field, include validator `FudisGroupValidators.atLeastOneRequired()` or `FudisGroupValidators.min()` in the validators array of `formGroup`.
To mark Checkbox Group as Required field, include validator `FudisGroupValidators.oneRequired()` or `FudisGroupValidators.min()` in the validators array of `formGroup`.

```
// In TypeScript file
Expand All @@ -119,7 +119,7 @@ myFormGroup = new FormGroup(
{
// controls
},
[FudisGroupValidators.atLeastOneRequired('At least one option must be selected!')]
[FudisGroupValidators.oneRequired('At least one option must be selected!')]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const basicFormGroup = new FormGroup<FudisCheckboxGroupFormGroup<object>>(
pineapple: new FormControl<boolean | null | undefined>(null),
orange: new FormControl<boolean | null | undefined>(null),
},
[FudisGroupValidators.atLeastOneRequired(new BehaviorSubject('No fruit picked! :('))],
[FudisGroupValidators.oneRequired(new BehaviorSubject('No fruit picked! :('))],
);

const ExampleTemplate: StoryFn<CheckboxGroupComponent> = (args: CheckboxGroupComponent) => ({
Expand Down Expand Up @@ -124,7 +124,7 @@ const withDisabledFormGroupOptions = new FormGroup<FudisCheckboxGroupFormGroup<o
pineapple: new FormControl<boolean | null | undefined | null>(null),
orange: new FormControl<boolean | null | undefined | null>({ value: null, disabled: true }),
},
[FudisGroupValidators.atLeastOneRequired(new BehaviorSubject('Please pick one! :('))],
[FudisGroupValidators.oneRequired(new BehaviorSubject('Please pick one! :('))],
);

const ExampleWithDisabledTemplate: StoryFn<CheckboxGroupComponent> = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class FieldsetExampleComponent {
// swedish: new FormControl(''),
// english: new FormControl(''),
// },
// [FudisGroupValidators.atLeastOneRequired(new BehaviorSubject('Course name is missing'))],
// [FudisGroupValidators.oneRequired(new BehaviorSubject('Course name is missing'))],
// ),
// description: new FormGroup({
// finnish: new FormControl('', [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,19 +250,19 @@ class DynamicValidatorExampleComponent {
{
summer1: new FormControl(null),
},
this._atLeastOneRequiredValidatorInstance,
this._oneRequiredValidatorInstance,
),
winter: new FormGroup<FudisCheckboxGroupFormGroup<object>>(
{
winter1: new FormControl(null),
},
this._atLeastOneRequiredValidatorInstance,
this._oneRequiredValidatorInstance,
),
working: new FormGroup<FudisCheckboxGroupFormGroup<object>>(
{
working1: new FormControl(null),
},
this._atLeastOneRequiredValidatorInstance,
this._oneRequiredValidatorInstance,
),
sport: new FormControl(null, [this._requiredValidatorInstance]),
});
Expand Down Expand Up @@ -339,8 +339,9 @@ class DynamicValidatorExampleComponent {
value: new Date(new Date().setDate(new Date().getDate() - 1)),
message: 'Date cannot be before yesterdays date',
});
private _atLeastOneRequiredValidatorInstance: FudisValidatorFn =
FudisGroupValidators.atLeastOneRequired('At least one option must be selected');
private _oneRequiredValidatorInstance: FudisValidatorFn = FudisGroupValidators.oneRequired(
'At least one option must be selected',
);

formExample: FormGroup;

Expand Down Expand Up @@ -396,14 +397,14 @@ class DynamicValidatorExampleComponent {

toggleRequiredFromOthers(removeControls: FormGroup<FudisCheckboxGroupFormGroup<object>>[]): void {
removeControls.forEach((control) => {
const required = control.hasValidator(this._atLeastOneRequiredValidatorInstance);
const required = control.hasValidator(this._oneRequiredValidatorInstance);

if (required) {
control.disable();
control.removeValidators(this._atLeastOneRequiredValidatorInstance);
control.removeValidators(this._oneRequiredValidatorInstance);
} else {
control.enable();
control.addValidators(this._atLeastOneRequiredValidatorInstance);
control.addValidators(this._oneRequiredValidatorInstance);
}

control.updateValueAndValidity();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ formExample = new FormGroup({
first: new FormControl(null),
second: new FormControl(null),
},
[FudisGroupValidators.atLeastOneRequired(new BehaviorSubject('Select at least one checkbox!'))],
[FudisGroupValidators.oneRequired(new BehaviorSubject('Select at least one checkbox!'))],
),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ class ExampleWithMultipleFormsComponent {
pineapple: new FormControl<boolean | null>(null),
orange: new FormControl<boolean | null | undefined>(null),
},
[FudisGroupValidators.atLeastOneRequired(new BehaviorSubject('No fruit picked! :('))],
[FudisGroupValidators.oneRequired(new BehaviorSubject('No fruit picked! :('))],
),
// formFour: new FormGroup({
// select: new FormControl<FudisSelectOption<object> | null>(
Expand Down Expand Up @@ -460,7 +460,7 @@ class FormContentExampleComponent implements OnInit {
// swedish: new FormControl(null),
// english: new FormControl(null),
// },
// [FudisGroupValidators.atLeastOneRequired(new BehaviorSubject('Course name is missing.'))],
// [FudisGroupValidators.oneRequired(new BehaviorSubject('Course name is missing.'))],
// ),
// description: new FormGroup({
// finnish: new FormControl(null, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
</ng-container>

<!--
Check parent level errors of FormGroup e. g. atLeastOneIsRequired
Check parent level errors of FormGroup e. g. oneRequired
-->
<ng-container *ngIf="formGroup?.errors && formGroup?.invalid">
<ng-container *ngFor="let error of formGroup?.errors | keyvalue">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const testFormGroupWithGroupValidator: FormGroup = new FormGroup(
swedish: new FormControl<string | null>(null),
english: new FormControl<string | null>(null),
},
FudisGroupValidators.atLeastOneRequired('There must be one value!'),
FudisGroupValidators.oneRequired('There must be one value!'),
);

const testControl = new FormControl(null, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export class InputWithLanguageOptionsComponent
/**
* At least one language input is required
*/
private _atLeastOneRequired: boolean = false;
private _oneRequired: boolean = false;

/**
* Property to check that control is not empty
Expand Down Expand Up @@ -171,17 +171,17 @@ export class InputWithLanguageOptionsComponent
initialRequiredCheck(): void {
this._requiredControls = {};

// TODO: change this._atLeastOneRequired to be fetched with getValidators
// TODO: change this._oneRequired to be fetched with getValidators

if (this.formGroup.errors?.['atLeastOneRequired']) {
this._atLeastOneRequired = true;
if (this.formGroup.errors?.['oneRequired']) {
this._oneRequired = true;

Object.keys(this.formGroup.controls).forEach((control) => {
this._requiredControls = {
...this._requiredControls,
[control]: {
value: this.formGroup.controls[control].value,
required: this._atLeastOneRequired,
required: this._oneRequired,
},
};
});
Expand All @@ -207,9 +207,9 @@ export class InputWithLanguageOptionsComponent
*/
isControlRequired(value: string, controlKey: string): void {
// If all controls are invalid run initialRequiredCheck()
if (this.formGroup.errors?.['atLeastOneRequired']) {
if (this.formGroup.errors?.['oneRequired']) {
this.initialRequiredCheck();
} else if (this._atLeastOneRequired && controlKey) {
} else if (this._oneRequired && controlKey) {
// Check how many controls are empty
this._requiredControls[controlKey].value = value;

Expand Down Expand Up @@ -237,7 +237,7 @@ export class InputWithLanguageOptionsComponent
}

// If two or more controls have a value, remove visible required text unless control has FudisValidators.required() or Validators.required
if (this._atLeastOneRequired && this._nonEmptyControls.length > 1) {
if (this._oneRequired && this._nonEmptyControls.length > 1) {
this._requiredControls = {};
Object.keys(this.formGroup.controls).forEach((control) => {
const isRequired = hasRequiredValidator(this.formGroup.controls[control]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
// ]),
// },
// [
// FudisGroupValidators.atLeastOneRequired(
// FudisGroupValidators.oneRequired(
// new BehaviorSubject('Give name in at least in one language'),
// ),
// ],
Expand All @@ -111,4 +111,4 @@

// export const ExampleWithAllRequired = TemplateAllRequired.bind({});

// export const ExampleWithAtleastOneRequired = TemplateOneRequired.bind({});
// export const ExampleWithOneRequired = TemplateOneRequired.bind({});
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class MockCheckboxGroupComponent {
blueberry: new FormControl<FudisCheckboxOption<object> | null>(null),
cloudberry: new FormControl<FudisCheckboxOption<object> | null>(null),
},
FudisGroupValidators.atLeastOneRequired('Choose at least one berry'),
FudisGroupValidators.oneRequired('Choose at least one berry'),
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
getMinFromValidator,
getMinLengthFromValidator,
hasRequiredValidator,
hasAtLeastOneRequiredOrMinValidator,
hasOneRequiredOrMinValidator,
} from './getValidators';
import {
FudisCheckboxGroupFormGroup,
Expand All @@ -34,33 +34,33 @@ describe('getValidators utility function', () => {
});
});

describe('hasAtLeastOneRequiredOrMinValidator', () => {
it('should return true with atLeastOneRequired validator group with checkbox group', () => {
describe('hasOneRequiredOrMinValidator', () => {
it('should return true with oneRequired validator group with checkbox group', () => {
const testFormGroup = new FormGroup<FudisCheckboxGroupFormGroup<object>>(
{
apple: new FormControl<boolean | null | undefined>(null),
fairTradeBanana: new FormControl<boolean | null | undefined>(false),
pear: new FormControl<boolean | null | undefined>(true),
},
[FudisGroupValidators.atLeastOneRequired('No fruit picked! :(')],
[FudisGroupValidators.oneRequired('No fruit picked! :(')],
);

const isRequired = hasAtLeastOneRequiredOrMinValidator(testFormGroup);
const isRequired = hasOneRequiredOrMinValidator(testFormGroup);

expect(isRequired).toEqual(true);
});

it('should return true with atLeastOneRequired validator group with InputWithLanguageOptionsFormGroup', () => {
it('should return true with oneRequired validator group with InputWithLanguageOptionsFormGroup', () => {
const testFormGroup = new FormGroup<FudisInputWithLanguageOptionsFormGroup>(
{
finnish: new FormControl<string | null>(null),
swedish: new FormControl<string | null>(''),
english: new FormControl<string | null>('Hello there!'),
},
[FudisGroupValidators.atLeastOneRequired('One must have some value!')],
[FudisGroupValidators.oneRequired('One must have some value!')],
);

const isRequired = hasAtLeastOneRequiredOrMinValidator(testFormGroup);
const isRequired = hasOneRequiredOrMinValidator(testFormGroup);

expect(isRequired).toEqual(true);
});
Expand All @@ -75,12 +75,12 @@ describe('getValidators utility function', () => {
[FudisGroupValidators.min({ value: 1, message: 'Pick one!' })],
);

const isRequired = hasAtLeastOneRequiredOrMinValidator(testFormGroup);
const isRequired = hasOneRequiredOrMinValidator(testFormGroup);

expect(isRequired).toEqual(true);
});

it('should return false when atLeastOneRequired validator is provided or min validator value is 0', () => {
it('should return false when oneRequired validator is provided or min validator value is 0', () => {
const testFormGroup = new FormGroup<FudisCheckboxGroupFormGroup<object>>(
{
apple: new FormControl<boolean | null | undefined>(null),
Expand All @@ -90,7 +90,7 @@ describe('getValidators utility function', () => {
[FudisGroupValidators.min({ value: 0, message: 'No need to select any actually' })],
);

const isRequired = hasAtLeastOneRequiredOrMinValidator(testFormGroup);
const isRequired = hasOneRequiredOrMinValidator(testFormGroup);

expect(isRequired).toEqual(false);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const hasRequiredValidator = (control: AbstractControl): boolean => {
return false;
};

export const hasAtLeastOneRequiredOrMinValidator = (group: FormGroup): boolean => {
export const hasOneRequiredOrMinValidator = (group: FormGroup): boolean => {
const validatorFn = group.validator;

if (validatorFn === null) {
Expand All @@ -32,7 +32,7 @@ export const hasAtLeastOneRequiredOrMinValidator = (group: FormGroup): boolean =
}),
);

const hasProperErrors: boolean = !!(errors?.['atLeastOneRequired'] || errors?.['min'].value > 0);
const hasProperErrors: boolean = !!(errors?.['oneRequired'] || errors?.['min'].value > 0);

return hasProperErrors;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ export interface FudisGroupValidatorsMinMaxSettings {
* Form Group Validators
*/
export const FudisGroupValidators = {
atLeastOneRequired,
oneRequired,
min,
max,
};

/**
* At least one option must be selected from a group
*/
function atLeastOneRequired(message: FudisValidatorMessage): FudisValidatorFn {
function oneRequired(message: FudisValidatorMessage): FudisValidatorFn {
return (controlGroup: AbstractControl): FudisValidationErrors | null => {
const { controls } = controlGroup as FormGroup;

Expand All @@ -34,7 +34,7 @@ function atLeastOneRequired(message: FudisValidatorMessage): FudisValidatorFn {

if (!theOne) {
return {
atLeastOneRequired: { message },
oneRequired: { message },
};
}
}
Expand Down
Loading
Loading