I would suggest using ajax to update the #upload_location on demand.
However, ajax on managed_file element is quite tricky. Because managed_file has its own ajax handling for uploading file. It only rebuildrebuilds the file element it selfitself and returns lack of data from other fields during during file upload ajax. So it need to be fixed in some hackyhacky way
Example code:
function mymodule_custom_form($form, &$form_state) { $input = &$form_state['input']; $values = &$form_state['values']; $form['folder_name'] = array( '#type' => 'textfield', '#title' => t('Folder Name'), '#submit' => array('mymodule_custom_form_folder_name_submit'), '#ajax' => array( 'callback' => 'mymodule_custom_form_folder_name_ajax', 'wrapper' => 'edit-file-ajax-wrapper', 'event' => 'keyup', ), ); // HACK: manually construct the folder_name value. // $form_state['values'] is empty for other field in file upload ajax // because it only rebuild the element rather then the whole form. if (!isset($values['folder_name']) && !empty($input['folder_name'])) { $values['folder_name'] = form_type_textfield_value($form['folder_name'], $input['folder_name']); } $form['file'] = array( '#type' => 'managed_file', '#title' => 'File', '#disabled' => empty($values['folder_name']) && empty($input['folder_name']), '#upload_validators' => array('file_validate_extensions' => array('jpg')), '#upload_location' => !empty($values['folder_name']) ? 'public://' . $values['folder_name'] : 'public://', ); function mymodule_custom_form_folder_name_submit(&$form, &$form_state) { unset($form['file']['#disabled']); $form_state['rebuild'] = TRUE; } function mymodule_custom_form_folder_name_ajax(&$form, &$form_state) { return $form['file']; }