Almost all of the sample block code you see out there (including blocks in the marketplace and blocks generated by Designer Content) use a javascript file called auto.js to validate the add/edit form fields. For example, you might have some code like this in the auto.js file to validate that a textbox is required:

ccmValidateBlockForm = function() {
    
	if ($('select[name=some_textbox_field]').val() == '' || $('select[name=some_textbox_field]').val() == 0) {
		ccm_addError('Some Textbox is required -- you must enter a value for this.');
	}

	return false;
}

While this approach works, I've never considered it ideal beacause:

  1. It requires an extra file in the block directory (and one with a non-obvious name)
  2. It's not where one would expect to find such validation code (if one weren't already familiar with the idiosyncrasies of Concrete5)
  3. It requires you to validate the fields in javascript, which is more difficult than doing so in PHP (because there is no javascript equivalent of the empty() function, and because you don't have access to the built-in validation helper functions that C5 provides).

Fortunately, I've recently discovered an easier and more intuitive way to handle block validation: just add a validate() function to your block's controller.php file! This function accepts an array of form data (usually called $args, just like the save() function), and should return a Concrete5 ValidationErrorHelper object. For example, to validate that a required textbox has something entered for it, you can put the following in your block controller.php file:

public function validate($args) {
	$e = Loader::helper('validation/error');
	
	if (empty($args['some_textbox_field'])) {
		$e->add('Some Textbox is required -- you must enter a value for this.');
	}
	
	return $e;
}