vivin / regula

Regula: An annotation-based form-validation framework in Javascript
126 stars 24 forks source link

Enhancement - support nested constraint - validations #36

Closed saunders99999 closed 11 years ago

saunders99999 commented 11 years ago

Background is in this issue https://github.com/vivin/regula/issues/35

Use Case checkbox input

when a user either leaves the input field or does a page submit, perform validation such that checkbox checked, input blank - validation warning checkbox checked, input filled in - no validation warning checkbox unchecked, input blank or filled in - no validation warning

Approach When writing custom constraints, update Regula to support a means so that a constraint can invoke another built-in or custom constraint. (Nested constraints/validations). This will help support use cases like above and add a lot of capability to custom constraints.

vivin commented 11 years ago

I will add this to 1.2.4. I will provide a way to reference validators from within an existing validator. I imagine I would do something like this:

function(params, validators) {
    //you can use the validators object to access the validator functions on constraints
}

I imagine that the validators object would have something like this:

validators.Core.Required.validator(this, params); //for core constraints.
validators.Custom.MyCustomConstraint.validator(this, params); //for custom/compound constraints.

I have to see how HTML5 constraints play into this as well.

vivin commented 11 years ago

This feature has been implemented. It is pretty similar to what I envisioned earlier, except that there is no separation of core and custom constraints. That seemed unnecessary. When you have a custom validator, you now receive a validator object that contains references to all-existing validators. This includes asynchronous validators as well.

For a synchronous validator, the signature of the validator becomes:

function(params, validator) {            
}

And for an asynchronous validator it becomes:

function(params, validator, resultCallback) {
}

The validator object exposes functions that match up to the constraint name, except that it is in camelCase. For example, for the Checked constraint, the validator is validator.checked, whereas for HTML5Required, the validator is validator.html5Required.

Keep in mind that for asynchronous constraints, you basically end up providing the resultCallback because that is the only way you can examine the result of an asynchronous validation.

The reason that these validators aren't exposed through the regula object is that they bypass the usual validation life-cycle, and so are minimally useful when used in isolation.

Also note that though it is possible to write compound constraints using the exposed validators, it is not recommended, since it bypasses the life-cycle for validating and defining compound constraints. Furthermore, in complicated scenarios, it is easy to end up creating a cyclical composition thereby resulting in an infinite loop.