Last active
August 29, 2015 14:03
-
-
Save Narretz/c7f781652544f3aa3660 to your computer and use it in GitHub Desktop.
angular.js input validation / parsing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Currently, processing angular input processing works like this: | |
$viewValue -> $parsers -> $modelValue -> $validators -> $modelValue -> model on $scope | |
$viewValue is the value that is displayed to the user in the input | |
the $viewValue is run through the $parsers pipeline | |
each parser receives the result of the previous $parser | |
$parsers can theoretically completely change the $viewValue and the result is the $modelValue | |
$modelValue is run through the $validators collection | |
each validator operates on the same $modelValue | |
if the $modelValue is invalid, it is not commited to the $model | |
Problems: | |
if the $model value is set, there's no initial validation (the $viewValue is set) | |
if the $modelValue is invalid, the $model is not set, and there's no way to set in anyway | |
-> use case: user can login with email or username. dev uses email field for mobile keyboards, but username will always | |
be invalid | |
it's not clear what should actually be validated: the $viewValue or the $modelValue | |
e.g. maxlength is checking the model value, but that doesn't work for objects (e.g. type="date") | |
sometimes it's necessary to validate both the $viewValue and the $modelValue | |
but it's diffcult to decide which should use what | |
-> maxlength, minlength: viewValue | |
-> email, url: viewValue / modelValue | |
-> date: modelValue | |
use case: masked input needs to parse the viewValue and validate it after. | |
it's not possible to have validators depend on each other (but it's actually a good thing that all validations are collected) | |
Goals: | |
- high level API that works by enhancing inputs and providing options to the developer in directives | |
- low level API that exposes the individual methods of the ngModelController to the developer in a consistent way | |
- option to write invalid model values to the $scope | |
- support for asynchronous validation | |
- debouncing validation | |
- easy way for devs to work with pure or partial server side validation (i.e. submitting the form) | |
- seamless integration of HTML5 validators | |
- consistent use of $parsers / $formatters and $validators | |
- make it easy to customize / overwrite validators | |
- dependant $validators? | |
Current bugs / implementation problems: | |
- invalidating a control with $setValidity blocks all further model updates and also empties the modelValue | |
- HTML5 validation (number) breaks other validations, because it lives in parsers | |
-> it currently aborts completely when it finds the error before angular number validator kicks in | |
-> this causes the parser pipeline to short-circuit | |
-> moving it to $validators means we overreport number / required ?? | |
- otherwise, the number validator would also run its own validation again | |
- calling $setViewValue does too much: sets the $viewValue, runs the $validators, sets $$invalidModelValue and $modeValue and writes the model to scope, all while aborting some of the operations in some circumstances | |
- it's not clear whether $parsers / $formatters should ever be able to $validate | |
- it's not clear when $parsers and $validators should run | |
Implementation notes: | |
- refactor the control handling to separate $setViewValue, $parse / $format, $validate and $writeModelToScope | |
- modeValue should always be set, only scope value should be deferred / (not) set because of validity | |
- three actions: checkValidity, reportValidity, setValue | |
- scenarios when checkValidation must run: (input and digest) | |
-> interpolated attribute for validator changes | |
-> native validation changes | |
-> when the viewValue (or modelValue) changes | |
-> when ngModelOptions decides to commit a $viewValue | |
-> debounced validationUpdate? | |
- when reportValidity must run | |
-> debounceModelUpdate | |
-> calling $setValidity | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment