<vega-form data-vega-form="form">
<vega-input data-vega-form="input" min="6" value="3" label="Min value is 6"></vega-input><br>
<vega-form data-vega-form="nestedForm">
<vega-input data-vega-form="nestedInput" max="12" value="15" Label="This is a nested form input"></vega-input>
</vega-form>
<vega-button id="getValue">Get Value</vega-button>
<vega-button id="valid">Validate</vega-button>
<vega-button id="reset">Reset</vega-button>
</vega-form>
const vegaForm = document.querySelector('vega-form');
document.getElementById('getValue').addEventListener('vegaClick', async () => {
window.alert(JSON.stringify(await vegaForm.getValue(), null, 2));
});
document.getElementById('reset').addEventListener('vegaClick', () => {
vegaForm.reset();
});
document.getElementById('valid').addEventListener('vegaClick', () => {
vegaForm.valid();
});
The vega-form
component is form logic helper designed to control vega field components (e.g. vega-input
, vega-select
, vega-input
, etc.) in an aggregate way. The advantage is that instead of needing to loop through each of the elements to access the form data, with vega-form
you have access to all of the data from a single touchpoint.
The features include the following:
vega-form
to do form reset/validation/prefill.isValid
property to track the form validation status in a reactive way.There are no specific properties which can be used for controlling the form component’s UI/UX, however there are a couple of components which can be used by developers who work with various states within vega-form
.
getValue
You can retrieve the value for all available field elements in the vega-form
asynchronously.
Use the following structure:
getValue<T>(option?: FormControlOption) => Promise<T>
This will return
Type: Promise<T>
For example:
const vegaForm = document.querySelector('vega-form');
const formValue = await vegaForm.getValue();
console.log(formValue);
isValid
isValid
is a Boolean which will indicate whether specific elements in a form are valid when given a set of validation criteria. A field will be controllable by the form if the field is one of the following:
vega-input
vega-select-input
vega-radio-group
vega-checkbox-group
vega-date-picker
vega-stepper
and that the element is not disabled and invisible.
isTouched
isTouched
is a Boolean object, which indicates if values of specific controlled elements within the form are changed. It is set to true
if values have been changed.
If any elements have been changed, isTouched
will be set to true. When used for resetting a form; when the form is reset it will be set to false
. It is also set to false
when called by the setValue
method.
data-vega-form
This is not technically a property of vega-form
but is instead a necessary flag used for form elements so that they may be controlled by either of the above elements.
For more details, view in Storybook
vegaValidate
vegaValidate
is dipatched when the validation result of the form is changed.
vegaFormSubmit
If the form is valid, the vegaFormSubmit
event is triggered when selecting submit or using the Enter
key. The form details is dispatched with this event.
vegaFormReset
Dispatched when the Reset
button is selected, the form will reset the value and then dispatch the event.
React
<VegaForm
onVegaFormValidate={ (e) => { console.log(e.detail) } }
onVegaFormSubmit={ (e) => { console.log(e.detail) } }
onVegaFormReset={ (e) => { console.log(e.detail) } }
...
></VegaForm>
Vue.js
<vega-form @vegaformvalidate="method" @vegaformsubmit="method" @vegaformreset="method" ...></vega-form>
JavaScript
document.getElementById("vega-form").addEventListener("vegaValidate", (e) => {
console.log(e.detail)
})
document.getElementById("vega-form").addEventListener("vegaFormSubmit", (e) => {
console.log(e.detail)
})
document.getElementById("vega-form").addEventListener("vegaFormReset", (e) => {
console.log(e.detail)
})
vega-form
proactively controls form status by specifying a manual trigger for the control flow.
Note: we currently support
vega-input
,vega-select-input
,vega-radio-group
,vega-checkbox-group
,vega-date-picker
,vega-stepper
, andvega-form
as field components.
You may use the following optional method for FormControlOption
parameters.
type FormControlOption = {
skipDisabled?: boolean;
skipInvisible?: boolean;
};
The following valid
method retrieves validation results for all vega field elements nested in the vega-form asynchronously. If the element is a vega-form
, it will call the valid()
method recursively.
valid(showError?: boolean | 'rule') => Promise<{ isValid: boolean; invalidFields: string[]; }>
The value options for showError
are true, false and ‘rule’. If set to true, it will override the shouldShowError
method for all rules and will always show errors if they exist. True is also the default value. If set to false it will override the shouldShowError
method for all rules and won’t show any errors. If set to ‘rule’, it will allow the shouldShowError
logic to decide when to show errors.
The above method returns:
Type: Promise<{ isValid: boolean; invalidFields: string[]; }>
.
Example
If we have a vega-form
with the below structure:
<vega-form data-vega-form="form">
<vega-input data-vega-form="input" min="6" value="3"></vega-input>
<vega-form data-vega-form="nestedForm">
<vega-input data-vega-form="nestedInput" max="12" value="15"></vega-input>
</vega-form>
</vega-form>
You can perform a validation using the following:
const vegaForm = document.querySelector('vega-form');
const validationResult = await vegaForm.valid();
console.log(validationResult);
This will then return:
{
"isValid": false,
"invalidFields": ["input", "nestedInput"]
}
If you do not wish to display a validation error, pass false
to VegaForm#valid()
const validationResult = await vegaForm.valid(false);
getValue
getValue
uses the following structure:
getValue<T>(option?: FormControlOption) => Promise<T>
which will then return
Promise<T>
Example
If we have a vega-form
with the following structure:
<vega-form data-vega-form="form">
<vega-input data-vega-form="input" value="inputValue"></vega-input>
<vega-form data-vega-form="nestedForm">
<vega-input data-vega-form="nestedInput" value="nestedInputValue"></vega-input>
</vega-form>
</vega-form>
You can retrieve the value using:
const vegaForm = document.querySelector('vega-form');
const formValue = await vegaForm.getValue();
console.log(formValue);
This returns:
{
"input": "inputValue",
"nestedForm": { "nestedInput": "nestedInputValue" }
}
setValue
setValue
uses the following structure:
setValue<T>(value: T, option?: FormControlOption) => Promise<void>
which will then return
Promise<void>
Example
If we have a vega-form
with the following structure:
<vega-form data-vega-form="form">
<vega-input data-vega-form="input"></vega-input>
<vega-form data-vega-form="nestedForm">
<vega-input data-vega-form="nestedInput"></vega-input>
</vega-form>
</vega-form>
The form value can be set by running:
const vegaForm = document.querySelector('vega-form');
await vegaForm.setValue({
input: 'inputValue',
nestedForm: { nestedInput: 'nestedInputValue' },
});
console.log(await vegaForm.getValue());
which will then return
{
"input": "inputValue",
"nestedForm": { "nestedInput": "nestedInputValue" }
}
reset
To reset the form, use the following structure:
reset(defaultValueMap?: unknown, option?: FormControlOption) => Promise<void>
Example:
async reset(defaultValueMap: unknown = {}, option?: { skipDisabled?: boolean; skipInvisible?: boolean; }): Promise<void>
This returns
Type: Promise<void>
Example
If we have a vega-form
with the following structure:
<vega-form data-vega-form="form">
<vega-input data-vega-form="input" value="inputValue"></vega-input>
<vega-form data-vega-form="nestedForm">
<vega-input data-vega-form="nestedInput" value="nestedInputValue"></vega-input>
</vega-form>
</vega-form>
You an reset the form value by running:
const vegaForm = document.querySelector('vega-form');
await vegaForm.reset();
console.log(await vegaForm.getValue());
This returns
{
"input": null,
"nestedForm": { "nestedInput": null }
}
Note
If you want to reset the form with a pre-defined default value for specific fields, you can add the value object with the same structure as the output of VegaForm#getValue()
:
const vegaForm = document.querySelector('vega-form');
await vegaForm.reset({ input: '', nestedForm: { nestedInput: '' } });
console.log(await vegaForm.getValue());
This returns:
{
"input": "",
"nestedForm": { "nestedInput": "" }
}
For each form component, the validation-rules
field will consume the ValidationRule
array. This array can only be attached to the input.
Use the formFieldValidationRule
interface.
export type EvaluateResult = {
isValid: boolean;
message: string;
};
export type FormFieldStatusMeta = {
touched: boolean;
modified: boolean;
disabled: boolean;
visible: boolean;
};
export interface FormFieldValidationRule<T> extends ValidationRule<T> {
canEvaluate(
input: unknown,
status?: FormFieldStatusMeta,
statusChanged?: (keyof FormFieldStatusMeta)[],
): boolean;
shouldShowError?(status?: FormFieldStatusMeta, statusChanged?: (keyof FormFieldStatusMeta)[]): boolean;
evaluate(input: T): EvaluateResult;
}
**Note:""
- The
statusChanged
array allows four strings:touched
,modified
,disabled
,visible
.- The
shouldShowError
function is optional and can be used for indicating whether or not to show an error message. If not provided, the default rule is!status.disabled && status.visible && (status.touched || status.modified)
const StringContainsVegaRule = {
canEvaluate(input: unknown, status: FormFieldStatusMeta): boolean {
return typeof input === 'string' && !status.disabled && status.visible;
}
shouldShowError(
status: FormFieldStatusMeta,
statusChanged: (keyof FormFieldStatusMeta)[],
): boolean {
return (
!status.disabled &&
status.visible &&
statusChanged.includes('modified') &&
(status.touched || status.modified)
);
}
evaluate: (input: string) => {
const isValid = input.indexOf('vega') > -1;
return { isValid, message: isValid ? '' : 'Input must contain "vega"' };
},
};
<VegaInput validation-rules = {[StringContainsVegaRule]} .. ></VegaInput>
In vega-form
, the form status is controlled proactively by specifying a manual trigger for the control flow.
The following field components are supported within vega-form
:
vega-input
vega-select-input
vega-radio-group
vega-checkbox-group
vega-date-picker
vega-stepper
vega-form
For vega-form
to be able to recognize the above components, the property data-vega-form="<field_name>"
must be set for each component. The <field-name>
can be used as an identifier during form control for each field.
All exposed methods in vega-form
are asynchronous.
FormControlOption
parameterstype FormControlOption = {
skipDisabled?: boolean;
skipInvisible?: boolean;
};
This method:
valid(showError?: boolean | 'rule') => Promise<{ isValid: boolean; invalidFields: string[]; }>
returns:
Promise<{ isValid: boolean; invalidFields: string[]; }>
Example:
If we have a vega-form
with the following structure:
<vega-form data-vega-form="form">
<vega-input data-vega-form="input" min="6" value="3"></vega-input>
<vega-form data-vega-form="nestedForm">
<vega-input data-vega-form="nestedInput" max="12" value="15"></vega-input>
</vega-form>
</vega-form>
We can validate it with:
const vegaForm = document.querySelector('vega-form');
const validationResult = await vegaForm.valid();
console.log(validationResult);
returning:
{
"isValid": false,
"invalidFields": ["input", "nestedInput"]
}
If you do not wish to show the validation error message, set vegaFormValid()
to be false:
const validationResult = await vegaForm.valid(false);
Keep forms short. Forms should generally include only the most necessary information you need from the user.
Use a UX-guided order. When ordering a form, structure it from a user’s perspective, not from the perspective of a database or application. Since data can typically be entered in any order, it’s best to put together the information in a logical order that will make sense to your target audience.
Grouping. Group information about things that are related to each other. Use of the nested inputs should help make this easier to include sub-arrays of data together, but make sure that information is presented in a way that makes the most sense to a user.
Single columns. Forms should typically be single-column in structure. Multiple columns can create an ambiguous workflow to the user, particularly if fields are aligned directly next to each other,
Match the input to the content. Use appropriate fields - make sure that type of input matches the type of content being requested. For example, don’t use a single-line input when you are requesting a larger amount of text, which would be better represented with a textarea field.