I'm building a basic hook_block implementation much like the example:

http://api.drupal.org/api/function/block_example_block/6

There's one thing I can't figure out: is there any way I can validate the form returned if $op is "configure" for hook_block? Say, for example, that I have a text field that needs to follow a particular format, or that can't be left blank?

Comments

Richard Blackborder’s picture

The best I've managed so far is something like this:

switch ($op) {
case 'save':
        if (!is_numeric($edit['mymodule_vid'])) {
        	form_set_error('', t('The vid must be numeric.'));
        } else {
        	//Saving the vid to the db
        	variable_set('mymodule_vid', $edit['mymodule_vid']);
        }
}

Whilst that stops bad data going in, the form isn't reprinting; the page goes back to the blocks list page and prints a success message under the form error message. And any changes to the block that aren't based in my $op=='save' code still take effect.

roopletheme’s picture

By the time you hook into the 'save' op of hook_block, it's too late. Instead, add an element validation handler in the 'config' op of hook_block. So if your form looks something like this:

 $form['mymodule_vid'] = array(
  '#type' => 'textfield', 
  '#title' => 'The VID',
); 

then add an element validation handler to the field, like this:

 $form['mymodule_vid'] = array(
  '#type' => 'textfield', 
  '#title' => 'The VID',
  '#element_validate' => array('mymodule_vid_validate'),
); 

and then provide the handler, like this:

 function mymodule_vid_validate($element) {
  if (($element['#value'] != '') && (!is_numeric($element['#value']))) {
    form_set_error('mymodule_vid', t('VID must be a number'));
  }
} 
Richard Blackborder’s picture

I did and it works, thanks!

Previously, I had also tried adding a form validation handler, based off the forms api reference:

//in the configure section of hook_block
$form['#validate'][] = 'mymodule_validate';

//Then later
function mymodule_validate($form, &$form_state) {
  if (($form_state['values']['mymodule_vid'] != '') && (!is_numeric($form_state['values']['mymodule_vid']))) {
    form_set_error('mymodule_vid', t('The vid must be a number'));
  }
} 

but it didn't work. The individual element validation handler you suggested does, though. Thanks :)

johnhanley’s picture

The above example illustrates using the #element_validate attribute, which is part of Forms API for Drupal 6.

Here's how to achieve the same thing using #validate for Drupal 5.

<?php
switch ($op) {
  case 'configure':
    $form['mymodule_vid'] = array(
      '#type' => 'textfield',
      '#title' => 'The VID',
      '#validate' => array('mymodule_vid_validate' => array()),
    );
}
?>

and then provide the handler, like this:

<?php
function mymodule_vid_validate($form) {
  if (($form['#post']['mymodule_vid'] != '') && (!is_numeric($form['#post']['mymodule_vid']))) {
    form_set_error('mymodule_vid', t('VID must be a number'));
  }
}
?>

-------------------------------------------------------

"If you don't read the newspaper you are uninformed;
if you do read the newspaper you are misinformed."
-- Mark Twain

emanaton’s picture

Thanks roopletheme!

It may be useful to some to implement more generic error handlers; e.g. if there are five fields to test to see if they are numeric, it would be nice to send them all to a single "is numeric" function rather than build out five identical blocks of code. For an example of what this might look like:

function _MODULE_validate_is_numeric($element) {
  if (!is_numeric($element['#value'])) {
    form_set_error(
      $element['#name'], 
      t(
        '%title% must be a number.', 
        array(
          '%title%'=>$element['#title'],
        )
      )
    );
  }
}