Blog

Eric Peterson

December 17, 2017

Spread the word


Share your thoughts

As web developers, a lot of our applications need to deal with CRUD actions and forms. It goes without saying that the information entered in to our applications needs to be valid. Client-side validation is important for user-experience, but is no substitute for good server-side validation.

As a holiday song reminds us, we should be "...making a list, checking it twice." Client-side validation is the first check. Server-side validation is the second. And an excellent module to help us with server-side validation is cbvalidation.

cbvalidation

cbvalidation lets you define constraints to ensure a given target object or struct meet. Constraints can be defined in three places: shared constraints in your config/ColdBox.cfc file, model constraints on the target component to validate, and ad hoc constraints in the validation method itself. Valid targets are components and structs.

Regardless of where the constraints are stored, they take the same shape:

// as well as storing these on `this.constraints`
// this could be a shared constraint defined in `config/ColdBox.cfc`
// or a struct passed directly to a validate method.
this.constraints = {
    "firstName" = {
        "required" = true
    },
    "lastName" = {
        "required" = true
    },
    "email" = {
        "required" = true,
        "type" = "email"
    },
    "age" = {
        "required" = false,
        "type" = "numeric",
        "min" = 0
    }
};

Validating Models

cbvalidation can validate any getters on an component, that is any method that follows the "get" & propertyName convention. (This includes properties on your component when accessors="true" is defined.) In your constraints, just reference the property name.

The most common place to store these constraints is on the component itself, under a this.constraints key. cbvalidation will use this struct by convention when validating the model. This means your validation for a user component can be as simple as validateModel( user );.

Validating Structs

Some times you need to validate a struct, usually the rc scope in ColdBox. An example of this is changing passwords. Usually a user is asked to type in the same password twice to ensure they are typing it in correctly. cbvalidation has a validator to help with that!

{
    "password" = {
        "required" = true
    },
    "passwordConfirmation" = {
        "required" = true,
        "sameAs" = "password"
    }
}

Those validation rules will do nicely. But where do we store this? Storing on the model itself is not a good idea because the passwordConfirmation field is required in this instance. When we are updating user data like normal, we won't want to enforce the passwordConfirmation field being required. This is a good use case to use ad-hoc validation:

var result = validateModel(
    target = rc,
    constraints = {
        "password" = {
            "required" = true
        },
        "passwordConfirmation" = {
            "required" = true,
            "sameAs" = "password"
        }
    }
);

This validation call would go right in the handler where updating a password happens in your application, solving the problem of validation that is only needed for certain actions in your application.

Shared Constraints

If your validation constraints don't belong on the model because they are not used every time, but they are used in multiple places still, a shared constraint may be the way to go.

Shared constraints are defined in your config/ColdBox.cfc under a validation.sharedConstraints key.

validation = {
    sharedConstraints = {
        "changedPassword" = {
            "password" = {
                "required" = true
            },
            "passwordConfirmation" = {
                "required" = true,
                "sameAs" = "password"
            }
        }
    }
};

Now the example from earlier is reduced down to this:

var result = validateModel( target = rc, constraints = "changedPassword" );

Now we don't have to repeat ourselves all over our application with the same validation rules while staying flexible with what rules we run at what times.

Custom Messages

Error messages can be customized by providing a key of the validation name suffixed with message, for instance requiredMessage for the required validation. These messages can reference special tokens which differ per validation type. Check out the docs for all the different tokens.

{
    "username" = {
        "required" = true,
        "requiredMessage" = "You forgot to enter your {field}"
        // will output "You forgot to enter your username"
    }
}

Custom Validators

Lastly, you can specify your own custom validators, a component that returns true or false depending on if the validation passes.

You can register a simple custom validator with the validator argument.

{
    "username" = {
        "required" = true,
        "validator" = "UniqueValidator@cborm"
    }
}

If you need custom validators with properties or multiple custom validators, you can also pass in a WireBox slug as the validator name:

{
    "username" = {
        "required" = true,
        "ExistsInDB" = {
            "table" = "users",
            "column" = "username"
        }
    }
}

Wrap Up

As you can see from the post length, this module is fully featured and ready to tackle all your validation needs in you application. Good luck and happy validating!

Add Your Comment

Recent Entries

Is Cloud the Answer for Your ColdFusion Dilemma?

Is Cloud the Answer for Your ColdFusion Dilemma?

Feeling the limits of an on-premise ColdFusion setup?

Many businesses face high costs, limited scalability, and performance bottlenecks, leaving them wondering if the cloud could be the answer.

In our FREE whitepaper, "Is Cloud the Answer for Your ColdFusion Dilemma?", we explore:

  • Benefits of Migrating to the Cloud: From cost savings to increased flexibility, find out what a cloud-based ColdFusion setup can do.
Cristobal Escobar
Cristobal Escobar
November 13, 2024
Mastering Events and Listeners in CBWIRE

Mastering Events and Listeners in CBWIRE

In CBWIRE, events and listeners are the backbone of building responsive, modular applications without relying heavily on JavaScript. This guide walks you through setting up and using CBWIRE events to create seamless interactions between components, from dispatching events in CFML and frontend templates to listening with Alpine.js and JavaScript. Learn how to make your applications feel dynamic and engaging by effortlessly connecting components. Whether you’re triggering events to update a dashboard or targeting specific parts of your app with dispatchTo, these techniques will empower you to create a modern, interactive CFML experience with ease.

Grant Copley
Grant Copley
November 11, 2024
10 Key Benefits of Hiring a Specialized ColdFusion Consulting Team

10 Key Benefits of Hiring a Specialized ColdFusion Consulting Team

ColdFusion remains a powerful and versatile platform for building dynamic web applications. However, keeping your ColdFusion environment optimized, secure, and scalable requires specialized expertise. Whether managing a long-standing ColdFusion application or planning new development projects, hiring a dedicated ColdFusion consulting and support team can be a game-changer for CTOs, CIOs, and developers. Here's why:

1. Expert Guidance on ColdFusion Web Development

...

Cristobal Escobar
Cristobal Escobar
November 08, 2024