Last updated October 2, 2011. Created by bmdhussain on July 2, 2010.
Edited by JuliaKM. Log in to edit this page.

Step 1:
Add the below code to template.php which replaces the delete checkbox with remove link.

<?php
function phptemplate_upload_form_current($form) {
 
$header = array('', t('Delete'), t('List'), t('Description'), t('Weight'), t('Size'));
 
drupal_add_tabledrag('upload-attachments', 'order', 'sibling', 'upload-weight');
  foreach (
element_children($form) as $key) {
   
// Add class to group weight fields for drag and drop.
   
$form[$key]['weight']['#attributes']['class'] = 'upload-weight';
   
$row = array('');
   
$form[$key]['remove']['#type'] = 'hidden'
   
$form[$key]['remove']['#attributes'] = array('class' => 'remove');
   
$form[$key]['remove']['#suffix'] = ' ' . t('<a class="remove" href="#">'.t('Remove').'</a>');
   
$row[] = array(
     
'data' => drupal_render($form[$key]['remove']),
     
'class' => 'remove container-inline'
   
);
   
$row[] = drupal_render($form[$key]['list']);
   
$row[] = drupal_render($form[$key]['description']);
   
$row[] = drupal_render($form[$key]['weight']);
   
$row[] = drupal_render($form[$key]['size']);
   
$rows[] = array('data' => $row, 'class' => 'draggable');
  }
 
$output = theme('table', $header, $rows, array('id' => 'upload-attachments'));
 
$output .= drupal_render($form);
  return
$output;
}
?>

Step 2:
Create a js file and place it with the
if (Drupal.jsEnabled) {
  Drupal.behaviors.modulename = function (context) {
  $('#upload-attachments a.remove', context).click(function() {
     var removeuploadedfile = function(data) {
         var result = Drupal.parseJson(data);
         $('#attach-wrapper').html(result['data']);
         Drupal.attachBehaviors(result['settings']);
         Drupal.attachBehaviors(document, Drupal.settings);
     }
     $(this).parent('td').parent('tr').html('Removing...');
     $(this).parent('td').children('input .remove').val(1);
     $.post('/removeattachment/js', $("#node-form").serialize(), removeuploadedfile);
     return false;
   });
}
}

Step 3:
Create a module to handle the remove request.
<?php
/**
* Implementation of hook_menu()
*/
function modulename_menu() {
   
$items['removeattachment/js'] = array(
       
'page callback' => 'modulename_remove_attachment',
       
'access arguments' => array('create ipaper'),
       
'type' => MENU_CALLBACK,
     );
    return
$items;
}
/**
* Implementation of hook_form_alter()
* @param <array> $form
* @param <array> $form_state
* @param <string> $form_id
*/
function modulename_form_alter(&$form, $form_state, $form_id) {
drupal_add_js(drupal_get_path('module', modulename') .'/modulename.js');
}
/**
* Remove files attached in forms
*/
function modulename_remove_attachment() {
  $cached_form_state = array();
  $files = array();
   drupal_add_js(drupal_get_path('
module', 'modulename') .'/modulename.js');
  // Load the form from the Form API cache.
  if (!($cached_form = form_get_cache($_POST['
form_build_id'], $cached_form_state)) || !isset($cached_form['#node']) || !isset($cached_form['attachments'])) {
   
form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.'));
   
$output = theme('status_messages');
    print
drupal_to_js(array('status' => TRUE, 'data' => $output));
    exit();
  }
 
$form_state = array('values' => $_POST);
 
// Handle new uploads, and merge tmp files into node-files.
 
upload_node_form_submit($cached_form, $form_state);
  if(!empty(
$form_state['values']['files'])) {
    foreach (
$form_state['values']['files'] as $fid => $file) {
      if (isset(
$cached_form['#node']->files[$fid])) {
        if(
$form_state['values']['files'][$fid]['remove'] == 1) { //Check whether the file remove link is clicked
         
unset($files[$fid]);
          unset(
$cached_form['#node']->files[$fid]);
        }
        else {
         
$files[$fid] = $cached_form['#node']->files[$fid];
        }
      }
    }
  }
 
$node = $cached_form['#node'];
 
$node->files = $files;
 
$form = _upload_form($node);
  unset(
$cached_form['attachments']['wrapper']['new']);
 
$cached_form['attachments']['wrapper'] = array_merge($cached_form['attachments']['wrapper'], $form);
 
$cached_form['attachments']['#collapsed'] = FALSE;
 
form_set_cache($_POST['form_build_id'], $cached_form, $cached_form_state);
  foreach (
$files as $fid => $file) {
    if (
is_numeric($fid)) {
     
$form['files'][$fid]['description']['#default_value'] = $form_state['values']['files'][$fid]['description'];
     
$form['files'][$fid]['list']['#default_value'] = !empty($form_state['values']['files'][$fid]['list']);
     
$form['files'][$fid]['remove']['#default_value'] = !empty($form_state['values']['files'][$fid]['remove']);
     
$form['files'][$fid]['weight']['#default_value'] = $form_state['values']['files'][$fid]['weight'];
    }
  }
 
// Render the form for output.
 
$form += array(
   
'#post' => $_POST,
   
'#programmed' => FALSE,
   
'#tree' => FALSE,
   
'#parents' => array(),
  );
 
drupal_alter('form', $form, array(), 'upload_js');
 
$form_state = array('submitted' => FALSE);
 
$form = form_builder('upload_js', $form, $form_state);
 
$output = theme('status_messages') . drupal_render($form);
 
// We send the updated file attachments form.
  // Don't call drupal_json(). ahah.js uses an iframe and
  // the header output by drupal_json() causes problems in some browsers.
 
$js_settings = drupal_add_js(NULL,NULL,'header');
  print
drupal_to_js(array('status' => TRUE, 'data' => $output,'settings' => call_user_func_array('array_merge_recursive', $js_settings['setting'])));
  exit;
}
?>

Clear the Cache and enable the module. If you attach any file it will provide you remove link instead of checkbox.

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.