0

I am creating Angular application including a reactive form. I also have a json schema file that should be addressed by that form, including both properties as form fields, and rules as form validation (simple and cross validation).

JSON schema: A and C required, B just required if A2

{
"$schema": "...",
"$id": "...",
...
"properties": {
    "A": {
        "description": "..."
        "type": "string"
        "enum": [
            "A1",
            "A2",
            "A3"
        ]
    },
    "B": {
        "description": "..."
        "type": "string"
        "enum": [
            "B1",
            "B2",
            "B3"
        ]
    },
    "C": {
        "description": "..."
        "type": "string"
        "enum": [
            "C1",
            "C2",
            "C3"
        ]
    },
},
"required": [
    "A",
    "C"
],
"allOf": [
    {
        "if": {
            "properties": {
                "A": {
                    "const": "A2"
                }
            }
        },
        "then": {
            "required": [
                "B"
            ]
        }
    }
]

}

Angular form.component.ts

...
myForm = new FormGroup(
  {
    'A': new FormControl('', Validators.required),
    'B': new FormControl('', ),
    'C': new FormControl('', Validators.required)
  },
  {
    validators: [myFirstValidator]
  }
);

cross-val.ts

import { ValidationErrors, ValidatorFn, FormGroup, AbstractControl } from "@angular/forms";

export const myFirstValidator: ValidatorFn =
(formGroupControl: AbstractControl): ValidationErrors | null => {
    const A = formGroupControl.get('A')
    const B = formGroupControl.get('B')

    if ( A!.value == "A2" && B!.value === "") {
        return { Brequired: true }
    }
    return null
};

Is there a way to create automatically the reactive form using just the json schema? At least, is there a way to create the cross validation file from the json schema?

3
  • Formly? formly.dev Commented Apr 26, 2022 at 15:40
  • I took a look at Formly but I can not find any example showing a cross-validation considering the "if" and "then" clauses of the JSON. I mean, if I am not mistaken, using formly the validation function has to be always created in Angular, it is not obtained directly from a json schema. What I wanted it would be to get the validation functions directly from the conditional validation clauses included in the JSON, so I wouldn't need to "hardcode" the validation functions since they would already be in the JSON. Commented Apr 26, 2022 at 16:11
  • Well, in Formly you have: a bunch of default validators formly.dev/examples/validation/built-in-validations conditional field rendering formly.dev/examples/field-options/hide-fields and also field matching capabilities formly.dev/examples/validation/matching-two-fields Honestly, the API is rich and extensible. Commented Apr 26, 2022 at 21:36

1 Answer 1

1

Yes it is, but it's not simple.

Step 0: Create a schema that you can easily parse

You already did that, though you might need to adjust it after you are done to be easily usable.

Step 1: Create custom validator factories

First you'll have to create factories for each and every validator that you want to be able to set via your JSON. Those factories must accept the values that the validator should check against.

For example if you want to use Angulars Validators.maxLength you'd have to create something like this: export const maxLengthValidatorFactory = validation => Validators.maxLength(validation.value);

After this is done you have to group all your validators in a way that can be easily accessed by generic functions. This would leave you with something like this:

export const VALIDATOR_FACTORIES = {
    maxLength: maxLengthValidatorFactory,
    ...
};

// for better typing
export declare type ValidatorKey = keyof typeof VALIDATOR_FACTORIES;

Step 2: Create the functionality to parse the JSON into Validators

Use Angulars Validators.compose() function. In there you can use the validations defined in your JSON and map them to the validator factories created in Step 1.

You can create the validator function in there by using the array accessor of the VALIDATOR_FACTORIES defined above.

Step 3: Create the form control

Now that you have your validator function(s) parsed in a way Angular can use you can go and create your FormControls. For that you can simply use the new FormControl() function and pass to it your parsed validator(s) as a parameter.

Step 4: Create the form group

Last you can go and put all the FormControls you just created into a FromGroup. You may create that one again by iterating over your JSON to create the keys that belong to the FormControls, if you want to have them named in a specific way.

Step 5: Create the HTML inputs

Now that you have your form group set up you can again iterate over the JSON the create the fitting HTML input elements.

By then setting the created FormGroup on their <form> and using the names for the controls that you already used inside the FormGroup you link everything up.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.