Search code examples
javajavascriptvalidationfieldtapestry

How to validate Tapestry's form fields with values that come from database?


I have a question regarding field validation with values present in the database.

I've been following http://jumpstart.doublenegative.com.au/jumpstart/examples/input/contributingvalidators as a guide, and it's been pretty straightforward for the most parts. However, I've hit a wall of some sort.

I'm trying to make my own validator:

public class UniqueValueProperty extends AbstractValidator<String, String> {
    // my validation stuff here
}

This is how I'm trying to contribute it:

public void contributeFieldValidatorSource(MappedConfiguration<String, Validator> configuration) {
    configuration.add(UniqueValueProperty.VALIDATION_NAME, new UniqueValueProperty());
}

So, to sum up:

  • I understand I need to provide a javascript code for client side validation, but I'm not sure how to actually access the DAO and do the check?

Edit:

Validator has a method you override, which does this:

Hook used by components to allow the validator to contribute additional attributes or (more often) client-side JavaScript

@Override
public void render(Field field, String constraintValue,
    MessageFormatter formatter, MarkupWriter writer, FormSupport formSupport) {

    formSupport.addValidation(field, VALIDATION_NAME, buildMessage(formatter, field, constraintValue), null);

If I understood it correctly, I can add some javascript code for client-side validation, right? Well, what I'd like to do in that part (dunno if it's possible) is to actually check for some things in my DB using the DAO, or even to pass more (dynamic) paremeters to validator, such as a list of values it should not trigger validation fail on.

Thanks :D

Edit: Lance, are you suggesting I could do this:

Tapestry.Validator.uniqueValueProperty = function(field, message, constraint) {

    field.addValidator(function(value) {
        if ((value != null) && (value.trim().length > 0)) {
            if (dao.valueExistsInColumn(value, constraint)) {
                throw message;
            }
        }
    });

};

where dao variable is injected in my validator object, contributed via addInstance method?


Solution

  • Use configuration.addInstance(name, class) instead of configuration.add(name, instance). Then tapestry will instantiate your validator and inject any dependencies (eg DAOs).

    EDIT

    eg:

    public class MyValidator extends AbstractValidator {
        @Inject private Dao dao;
    
        public void render(Field field, String constraintValue, MessageFormatter formatter, MarkupWriter writer, FormSupport formSupport) {
            // this is the serverside representation of the field which will be rendered to HTML
            Element fieldElement = writer.getElement();
            List<String> values= dao.getSomeList(constraintValue);
            String valuesAsString = values.toString();
    
            // add an attribute to the DOM, this can be referenced in javascript later
            fieldElement.attribute("data-values", valuesAsString);
            formSupport.addValidation(...);
        }
    }
    

    The field will now have a "data-some-list" in the HTML/DOM which your javascript validator can now access. If using jquery, it has built in support for "data-" attributes. eg:

    var valuesAsString = $(#someField").data("values");
    

    Or

    var valuesAsString = $(#someField").attr("data-values");