3

I'm using Valdr on my project and I need to validate that a date input "startDate" is before another date input "endDate".

<input id="startDate" name="startDate" type="text" ng-model="project.startDate"/>
<input id="endDate" name="endDate" type="text" ng-model="project.endDate"/>

I know that, without Valdr, this problem can be solved using a custom directive, as shown here: Directive for comparing two dates

I found a little unclear how to create a custom validator on Valdr that uses the values of other fields.

Community
  • 1
  • 1

4 Answers4

1

The answer is short but dissatisfactory: valdr does currently not support this. There is an open feature request on GitHub, though.

Marcel Stör
  • 22,695
  • 19
  • 92
  • 198
0

Until the feature gets implemented in valdr, you can use your own validator directive and kind of make it talk to valdr. The directive can require a 'form' and can get the names of the date models you want to compare. Then you do your logic to compare the two values and set the validity of the appropriate 'ngModelController'. Since you need to provide an error when setting the validity to that model, the error name will be your connection with valdr.

After that, you just only need to map the error in the 'valdrMessage' service:

.run(function (valdrMessage) {

valdrMessage.angularMessagesEnabled = true;

valdrMessage.addMessages({
  'date': 'Invalid date!'
});

});

Valdr will show the message bellow the invalid field as usual.

peso_junior
  • 400
  • 2
  • 8
0

Actually you can solve this through a custom validator, which can get another field and compare the values with each other. The code below is using the valdr-bean-validation for serverside generation of valodation.json.

If you want to use it without this, just look into the JS code and add the validator in your validation.json manually.

Java Annotation (serverside declaration of the valdr validator):

package validation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR,
        ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
public @interface DateFormat {

    String message();

    Class[] groups() default { };

    String beforeFieldName();
}

Java Bean (usage of the annotation, this class has to be used in the generation of validation.json):

package pojo;

import validation.DateFormat;

public class RegistrationPojo implements BasePojo {

    @NotNull(message = "message.date1.required")
    private Date date1;

    @NotNull(message = "message.date2.required")
    @DateFormat(message = "message.date2.date", beforeFieldName = "date1")
    private Date date2;

}

JS (implementation of the custom validator and registering it in valdr):

module.factory('validation.DateFormat', [
    function () {
    return {
        name: 'validation.DateFormat',
        validate: function (value, constraint) {
            var minOk = true;
            var maxOk = true;
            var format = false; // constraint.pattern is mandatory
            //do not validate for required here, if date is null, date will return true (valid)

            console.log("my date validator called");
            console.log("    beforeFieldName: " + constraint.beforeFieldName);

            var field = document.querySelector('[name="' + constraint.beforeFieldName + '"]');
            console.log("field value: " + (field ? field.value : "null"));
            return (!field || value > field.value);
        }
    };
}]);

module.config([
    "valdrProvider", 
function(valdrProvider) {
    valdrProvider.addValidator('validation.DateFormat');
}]);
Manuel Manhart
  • 4,819
  • 3
  • 24
  • 28
0

You could go with this solution:

  1. Have a bool value calculated upon changes in any of the date fields - a value indicating if the validation rule is met
  2. Create a simple custom validator to check if that value is true or not
  3. Register your validator and add a constraint for that calculated value
  4. Place a hidden input for that calculated value anywhere you like your validation message to appear