3

I've tried to get into custom element creation but ran into problems with #value_callback and when #element_validate, more specifically their lack of documentation.

Imagine you have a custom element called db_connection whose output is supposed to be a is supposed to be an SQL connection string.

The element itself consist of a few select elements and one textfield. The user then simply selects (let's say) the database in the first one, table in the second one, and writes numerical of desired row in the last textfield.

My question is, when should you go trough the individual inputs and create the SQL connection string from them? Should it be in #value_callback or in #element_validate?


The names suggest the latter should be more suitable but my experience so far say the very opposite... It also seems to me that other modules (date) do it in the former one.

If one should really do it in #value_callback then how should he approach validation? As far as I know, the value callback is called before validation happens so it might have to deal with invalid individual inputs from which it might be impossible to construct the final output (SQL connection string in our example)?

And if it in fact is to be done in #value_callback than what purpose does #value_callback serve? What should it do, what should it return, ...?


As of my research:

This article suggests that one should use #value_callback to transform 'default_value' to element friendly data form and use #element_validate to transform inputed data to store / later use friendly form.

So basically it suggests to go with #element_validate for the SQL connection string creation and use the #value_callback only to properly set up the element in case the SQL connection string is given as default value.


In addition to this question I also have this one (that is more about #value_callback). Already partially answered.

5
+50

#element_validate:

A list of custom validation functions. The validation functions must use form_error() or form_set_error() to flag the element as having an error if the validation fails.

Use this when you want to validate the input into your custom element, and inform users of any failures. Code example of such a validation function:

function myelement_validate($element, &$form_state, $form) {
   if (empty($element['#value'])) {
     form_error($element, t('This field is required.'));
   }
}

#value_callback:

Specifies the name of a custom value function that implements how user input is mapped to an element's #value property.

Use this when you simply want to change the state of something in your element based on contextual information. Don't use this method if that state-change has the potential to cause an error that the user should be made aware of; use a validate function in that instance instead.

Code example:

function file_field_widget_value($element, $input = FALSE, $form_state) {
  if ($input) {
    // Checkboxes lose their value when empty.
    // If the display field is present make sure its unchecked value is saved.
    $field = field_widget_field($element, $form_state);
    if (empty($input['display'])) {
      $input['display'] = $field['settings']['display_field'] ? 0 : 1;
    }
  }
}

So to your question:

when should you go trough the individual inputs and create the SQL connection string from them?

If this is a process that needs to be validated, then in a validation function. If it's something that just needs to be done, regardless of the input, then it goes in the value callback function.

Reading through the code in a bunch of the core value callbacks should clear up the confusion even better:

Notice that nothing in any of those functions relates to validation of the input.

Also see form_builder(), where the callback is actually used.

2

If you're developing a module to be shared on drupal.org, certainly use #element_validate. #element_validate takes an arbitrary number of callbacks, while #value_callback only one. So, leave #value_callback for a third-party site developer who might have some use for it.

In your hook_element_info(), give your element both a #process callback and an #element_validate callback.

In the #element_validate, both validate the form values and use form_set_value() to transform the input fields into the connection string you want. (Or, build a data structure that contains both the input fields and the computed value.)

In the #process callback, be sure to accept, as #default_value, the computed value from your validate callback. That is, you may have to parse the connection string to extract proper default values for the select elements and textfield.

  • I'm not developing a module to be shared and honestly just that someone else might use #value_callback doesn't seem to me as proper reason to do it this way. While it is pragmatic I'd appreciate an architecturally right approach better. – Petrroll Aug 10 '14 at 14:34
  • 1
    IMHO, it is the right architecture whether making a contrib module or not. It's how #element_validate is meant to be used. Why do you think otherwise? – Dave Cohen Aug 11 '14 at 21:08
  • Because the name '#value_callback' sort of suggests that that is the place where value processing should take place. And - similarly - #element_validate doesn't sound like anything connected to value processing. – Petrroll Aug 12 '14 at 14:10
  • #element_validate callback is certainly intended for validation. As a benefit, form_set_value() allows you to tweak values. You should only call form_set_value() after the input has passed validation. There's not much incentive to add another form api callback with a name you prefer when #element_validate is called at the proper time and supports what you are trying to do. – Dave Cohen Aug 12 '14 at 20:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.