سؤال

Hours of scouring the Drupal community pages in search of answers to a seemingly simple question has yielded no results so far, so hopefully you can help!

Can anyone describe how, in a custom form, with FAPI, to implement an input element of type 'nodereference_autocomplete'? For the uninitiated, this is an AJAX-decorated textfield which autocompletes on a field of a matching referenced node, provided by the CCK module. I would like to leverage this functionality in my own Drupal 6 module.

The submitted value must be the nid of the referenced node. Additionally, Instructions for constraining the autocomplete path to include only nodes of type 'article' and 'blogpost' would be most appreciated.

Thanks for your help with this most basic of questions!

هل كانت مفيدة؟

المحلول

I believe that since you're not using CCK directly, you'll need to write a bit of code in a custom module that emulates the CCK behavior. You can use the FAPI's autocomplete features.

Your form_alter or form definition code might look like this:

$form['item'] = array(   
  '#title' => t('My autocomplete'),
  '#type' => 'textfield',   
  '#autocomplete_path' => 'custom_node/autocomplete'  
); 

Since you need to limit by node type, you'll probably need to create your own autocomplete callback as well. That will look something like this:

function custom_node_autocomplete_menu() {
  $items = array();
  $items['custom_node/autocomplete'] = array(
      'title' => '',
      'page callback' => 'custom_node_autocomplete_callback',
      'access arguments' => array('access content'),
      'type' => MENU_CALLBACK,
    );
  return $items;
}

function custom_node_autocomplete_callback($string = '') {
  $matches = array();
  if ($string) {
    $result = db_query_range("SELECT title, nid FROM {node} WHERE type IN('article', 'blogpost') AND LOWER(title) LIKE LOWER('%s%%')", $string, 0, 5);
    while ($data = db_fetch_object($result)) {
      $matches[$data->title] = check_plain($data->title) . " [nid:" . $data->nid . "]";
    }
  }
  print drupal_to_js($matches);
  drupal_exit();
}

Then you'll need to write code to extract the node id from the submitted value. Here's the code that CCK uses to do that:

preg_match('/^(?:\s*|(.*) )?\[\s*nid\s*:\s*(\d+)\s*\]$/', $value, $matches);
if (!empty($matches)) {
  // Explicit [nid:n].
  list(, $title, $nid) = $matches;
  if (!empty($title) && ($n = node_load($nid)) && trim($title) != trim($n->title)) {
    form_error($element[$field_key], t('%name: title mismatch. Please check your selection.', array('%name' => t($field['widget']['label']))));
  }
}
else {
  // No explicit nid.
  $reference = _nodereference_potential_references($field, $value, 'equals', NULL, 1);
  if (empty($reference)) {
    form_error($element[$field_key], t('%name: found no valid post with that title.', array('%name' => t($field['widget']['label']))));
  }
  else {
    // TODO:
    // the best thing would be to present the user with an additional form,
    // allowing the user to choose between valid candidates with the same title
    // ATM, we pick the first matching candidate...
    $nid = key($reference);
  }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top