-
Notifications
You must be signed in to change notification settings - Fork 161
Grid Validation Specification
- Overview
- User Stories
- Functionality
- Test Scenarios
- Accessibility
- Assumptions and Limitations
- References
Grinders
Developer Name Maya Kirova
Designer Name
- Svilen Dimchevski | Date: 10 August, 2022
- Konstantin Dinev | Date:
- Stamen Stoychev | Date: 09 August, 2022
- Deyan Kamburov | Date: 09 August, 2022
- Radoslav Mirchev Name | Date:
- Damyan Petev | Date:
Version | Users | Date | Notes |
---|---|---|---|
1 | Maya Kirova | 11/07/2022 | Initial Draft |
2 | Svilen Dimchevski | 21/07/2022 | Updated Functionality section |
3 | Maya Kirova | 03/08/2022 | Update and polish specification |
igxGrid
should allow validating user input when editing cells/rows.
Should extend Angular's reactive forms validation functionality to allow easier extensibility and maintainability.
Should show visual indicators (like error message, error styles etc.) when a cell/row enters invalid state.
Should have an option to prevent editing from continuing in case of invalid input.
End-to-end user experience prototype
- Should allow defining declaratively the default angular supported validators on the
igx-column
components. For example:
<igx-column required ...>
These should then be used for cell validation.
-
Should expose the generated
FormGroup
for the edited row/cell so that it can be customized by the user. -
Should allow customizing the error's.
Developer stories:
As a developer, I want to be able to:
- declaratively set Angular's forms validators on the columns of the grid, so that I can validate the related cells on edit.
- set my own custom validator, so that I can validate according to my business requirements.
- customize the error messages.
- access to the
FormGroup
used for validation so that I can further customize it. - prevent users from leaving edit mode for a cell/row when there are errors.
- get all invalid values before commit.
- set the validation trigger that would start validation on my inputs - similar to updateOn.
End-user stories:
- Story 1: As an end-user, I want to get a descriptive validation message when I enter an invalid value, so that I can fix it.
3.1. Design handoff- https://www.figma.com/file/fmatez7lHAxkXHhybPIhIa/Validation-message?node-id=0%3A1
Validation state is managed and stored in a validation service. The service exposed the following public apis:
-
valid
- returns if current state is valid. -
getInvalid
- returns just the invalid record states. -
markAsTouched
- marks the related record/field as touched. -
clear
- clears the validity states.
Related public interfaces are as follows:
export interface IRecordValidationState {
id: any;
valid: boolean;
state: IFieldValidationState[];
}
export interface IFieldValidationState {
field: string,
valid: boolean,
errors: ValidationErrors
}
Validity is updated when editing rows/cells via the UI or via the api.
However errors will be shown only if the row/cell has been touched by the user (via user interaction with the editor) or if it is manually marked as touched via the markAsTouched
API.
Only exception is the adding row, where all cell will be marked as touched when the row is added.
When global grid validity changes from valid to invalid or vice versa the validationStatusChange
event of grid will be emitted with the new state.
- Batch editing
When batch editing is enabled transactions can modify the grid state using the undo
/redo
API.
In those case validation state will update accordingly. Validation will re-trigger on the new value and the new state will be reflected in the validation service.
- Submitting invalid values
It is up to the developer on application level to decide whether to allow invalid values to be submitted into the grid.
-
If no invalid values should be allowed to be entered in the data/transactions then the developer can cancel the
cellEdit
,rowEdit
events to prevent the grid from entering an invalid state. -
In case the developer would like to handle the invalid records himself he can do so via the
getInvalid
API from thegrid.validation
object. He can collect the invalid record information and decide how to proceed - whether to clear them, propt the user to fix them, allow commiting them etc., depending on the use case.
In case the grid data is changed after an user has made editing operations on rows/cells, existing validation states will be re-evaluated based on the new data and transactions by row ids.
In case updates are no longer relevant to the new data (i.e. a completely new unrelated data is set to the grid) it would be recommended to clear both the transaction and validation states of the grid via their clear
API methods.
3.2. Developer Experience
3.2.1 Configuration
- Validating via template-driven configuration
You can use the predefined angular forms validators declaratively on the igx-columns
to enable validation for the related cells while editing:
<igx-column required minlength="4" ...>
These will then be injected for the cell when edit and used for validation.
The following will be supported out of the box, as we will extend the base angular directives to work on the igx-column
:
- required
- min
- max
- minlength
- maxlength
- pattern
You can also defined your own custom directive that extends the column validator directive, for example:
@Directive({
selector: '[appForbiddenName]',
providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true}]
})
export class ForbiddenValidatorDirective extends Validators {
@Input('appForbiddenName')
public forbiddenName = '';
validate(control: AbstractControl): ValidationErrors | null {
return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control)
: null;
}
}
And use this in the column template:
<igx-column appForbiddenName='bob' ...>
- Validating in reactive forms
We also expose the FormGroup
that will be used for validation when editing starts on a row/cell via a formGroupCreated
event. You can add validators to it for the related fields:
<igx-grid (formGroupCreated)='formCreateHandler($event)' ...>
public formCreateHandler(formGr: FormGroup) {
// add a validator
const prodName = formGr.get('UserName');
prodName.addValidators(forbiddenNameValidator(/bob/i))
}
3.2.2 Customizing errors
The editing template can be modified with a custom one per column, for example:
<igx-column ... >
<ng-template igxCellValidationError let-cell='cell'>
<div *ngIf="cell.errors?.['forbiddenName']">
This name is forbidden.
</div>
</ng-template>
</igx-column>
3.2.3 Prevent edit end when input is invalid
The editCell
/editRow
events can be canceled in case the isValid
argument is false.
<igx-grid (cellEdit)='cellEdit($event)' ...>
public cellEdit(evt) {
if (!evt.valid) {
evt.cancel = true;
}
}
In that case the cell will remain in edit mode until a valid value is set.
3.2.3 Customizing the validation trigger.
The validation trigger can be set via the validationTrigger
property:
<igx-grid #grid validationTrigger='blur'></igx-grid>
Valid values are change
, blur
.
3.3. Globalization/Localization
Default errors originating from the predefined angular forms validators that are set on the columns will have a default error message (i.e. required - This field is required.)
Default error message strings will need to be localized.
3.4. Keyboard Navigation
Keys | Description |
---|---|
3.5. API
Name | Description | Type | Default value | Valid values |
---|---|---|---|---|
validationTrigger | Gets/Sets the trigger for validators used when editing the grid. | GridValidationTrigger | change |
'change' , 'blur' |
Name | Description | Cancelable | Parameters |
---|---|---|---|
formGroupCreated | Event emitted when validation form group is created for an edited row/cell. Emits the form group that with the form controls that will be used for validation. | false | FormGroup |
validationStatusChange | Event emitted when validation status changes from valid to invalid or vice versa | false | Validity |
Name | Description | Return type | |
---|---|---|---|
valid | Returns whether current state is valid. | boolean |
Name | Description | Return type | Parameters |
---|---|---|---|
getInvalid | Returns all invalid record states. | IRecordValidationState[] | |
markAsTouched | Marks the associated record or field as touched. | void | id: any, field?: string |
clear | Clears validity state by id or clears all states if no id is passed. | void | id?:any |
Automation
- should allow setting built-in validators via template-driven configuration on the
<igx-column>
. - should allow setting custom validator via template-driven configuration on the
<igx-column>
. - should allow setting validators on the exposed FormGroup object.
- should allow setting validation triggers - 'change' , 'blur'.
- should mark invalid cell with
igx-grid__td--invalid
class and show the related error cell template. - should show the error message on error icon hover and when the invalid cell becomes active.
- should allow customizing the error message template.
- should allow preventing edit mode for cell/row to end by canceling the related event if
isValid
event argument is false. - should trigger the
validationStatusChange
event on grid when validation status changes. - should return invalid record states using
getInvalid
api. - should allow clearing validation states via
clear
api. - should apply aria attributes
aria-invalid
,aria-errormessage
to cell and editor when cell is invalid.
- should update validity state but should not show error message when setting new values via grid api(
updateRow
,updateCell
).
- should update validity states on transaction's
undo
/redo
api. - should not show error if record with invalid state is deleted.
ARIA Support
When the cell becomes invalid the following attributes are applied to it:
-
aria-invalid
- set to true. -
aria-errormessage
- set to the error message tooltip id that contains details on the error.
Assumptions | Limitation Notes |
---|---|