I've tacked a variation on this before and this was the only solution I found that didn't have problems of some sort.
The key is not to skip all validation as you may add security holes so you have to specifically skip required validation. - Specifically what I'm getting at here is don't use #limit_validation_errors.
You cannot stop drupal core from validating that required fields are not empty, so you have to make the fields not required when they get validated.
Note that this example will make all fields not required, so you'll have to add some logic to only do that for the fields you are interested in.
I couldn't add this because I don't have enough info about your setup.
In your form add this:
// Add an after build callback so we can modify the form before validation.
$form['#after_build'][] = 'MYMODULE_form_after_build';
Then add that after build function and a helper function:
/**
* Form after build callback.
*
* We are using this to modify the form after it has been submitted,
* but before it has been validated.
* This means we can remove required flags for certain fields.
*
* @param array $element
* An associative array containing the structure of a form element.
* In this case the form.
* @param array $form_state
* The form state array.
*
* @return array
* An associative array containing the structure of a form element.
*/
function MYMODULE_form_after_build($element, &$form_state) {
// Check that the form has been submitted.
if ($form_state['process_input']) {
// Deal with required fields.
_MYMODULE_remove_required($element);
}
return $element;
}
/**
* Make elements of a form not required.
*
* This example function will make all required fields not
* required.
* In your case you want to only do certain fields so you will have
* to add logic in here to only affect some fields.
* You could do this based on field name or some other flag you have
* set, or whatever.
*
* @param array $elements
* An associative array containing the structure of a form.
*/
function _MYMODULE_remove_required(&$elements) {
// Recurse through all children.
foreach (element_children($elements) as $key) {
if (isset($elements[$key]) && $elements[$key]) {
_MYMODULE_remove_required($elements[$key]);
}
}
if (!empty($elements['#required'])) {
$elements['#required'] = FALSE;
}
}