6

Is it possible to show in a select list, another field instead of the Title when referencing a node?

7

As dobeerman says you can use a View as a source, but CCK does some playing with the View behind the scenes (I just found out as a result of this question;). If you look in nodereference.module at the function _nodereference_potential_references_views() you'll find the following code:

// We do need title field, so add it if not present (unlikely, but...)
$fields = $view->get_items('field', $display);
if (!isset($fields['title'])) {
  $view->add_item($display, 'field', 'node', 'title');
}

// If not set, make all fields inline and define a separator.
$options = $view->display_handler->get_option('row_options');
if (empty($options['inline'])) {
  $options['inline'] = drupal_map_assoc(array_keys($view->get_items('field', $display)));
}
if (empty($options['separator'])) {
  $options['separator'] = '-';
}
$view->display_handler->set_option('row_options', $options);

So this means that

  • if you don't include a title field then it will be included for you;
  • if you don't make all fields inline and define a separator then it will be done for you.

So if you configure the title field to be hidden, and specify an appropriate separator, you should be able to create just about any effect. If you can't achieve what you want with a view (eg. ordering nodes by their menu position) then you want to use a different approach.

You could create your own CCK widget, or (simpler) you can use a form_alter hook. If you do the latter, you can't edit the form the normal way because CCK hasn't processed the form at this stage - you'll want to use a #after_build function.

I have an example of the second approach used to show nodereferences ordered by the menu if you're interested.

/**
 * Implements hook_form_alter().
 */
function banners_form_alter(&$form, &$form_state, $form_id) {

  // Modify nodereferences for banners so that pages are shown in primary links
  // order.
  if ($form['#id'] === 'node-form' && isset($form['#field_info']['field_pages'])) {

    if (!isset($form['#after_build'])) {
      $form['#after_build'] = array();
    }
    $form['#after_build'][] = 'banners_after_build';
  }
}

/**
 * After_build callback for modifying CCK field select options.
 */
function banners_after_build($form, &$form_state) {
  // Get the menu data
  $new_options = banners_generate_page_options();

  if (isset($form['#field_info']['field_pages'])) {
    $old_options = $form['field_pages']['nid']['nid']['#options'];
    $final_options = banners_process_options($new_options, $old_options);
    $form['field_pages']['nid']['nid']['#options'] = $final_options;
  }

  // Return new form
  return $form;
}

/**
 * Uses the old options to filter out unreferenced nids and add those that 
 * weren't detected in a menu structure to the other option group. 
 * @param $new_options
 *   The options list created by scanning the menus.
 * @param $old_options
 *   The options list originally passed to the form.
 *   
 * @return
 *   The final options list with option groups for each menu and for orphans.
 */
function banners_process_options($new_options, $old_options) {
  // Have to assume that $old_options could get quite large, whereas 
  // $new_options is based on menus, and shouldn't get too large.

  // Iterate through $new_options (the menu nids) and remove nids from
  // $old_options that exist in $new_options, and remove nids from $new_options
  // that don't exist in $old_options. After this $old_options has valid nids
  // that aren't under the menu hierarchy.
  foreach ($new_options as $menu_title => $options) {
    foreach ($options as $nid => $title) {
      if (isset($old_options[$nid])) {
        unset($old_options[$nid]);
      }
      else {
        unset($new_options[$menu_title][$nid]);
      }
    }
  }

  $final_options = array();

  // If the field is not marked required, there'll be an option for - None -
  // and it's keyed to the empty string.
  if (isset($old_options[''])) {
    $final_options[''] = $old_options[''];
    unset($old_options['']);
  }

  $final_options += $new_options;

  $final_options['Others'] = $old_options;

  return $final_options;
}

/**
 * Generates FAPI options for the allowed menus' node links.
 * 
 * @return
 *   A FAPI options array with all node links on the allowed menus (NB this has
 *   not been filtered in any other way).
 */
function banners_generate_page_options() {

  $menus = array('primary-links', 'menu-top-menu');
  $options = array();

  foreach ($menus as $menu_name) {
    $tree = menu_tree_all_data($menu_name);
    $menu = menu_load($menu_name);
    $options[$menu['title']] = _banners_process_tree($tree);
  }

  return $options;
}

/**
 * Recursive function to generate the options array, keyed by nid.
 */
function _banners_process_tree($tree, $depth = 0) {

  $options = array();

  foreach ($tree as $item) {
    $matches = array();
    if (preg_match('~^node/(\d+)$~', $item['link']['link_path'], $matches)) {
      // Link points to a node
      $nid = $matches[1];
      $options[$nid] = str_repeat('--', $depth) . ' ' . $item['link']['title'];
      if ($item['below']) {
        $options += _banners_process_tree($item['below'], $depth + 1);
      }
    }
  }

  return $options;
}
  • Hi Andy. I am quite interested in the hook_form_alter approach. Can you share the example? Cheers! – gilzero Apr 4 '11 at 12:17
  • @gilzero - done – Andy Apr 4 '11 at 13:26
5

When you create nodereference field you can select 'View' used to select the nodes in 'Advanced - Nodes that can be referenced (View)' fieldset. Also you can pass argument to this view by default.

  • This is by far the easiest way. The drop-down will show whatever fields you add to the view. – electblake Apr 4 '11 at 14:09
  • +1 forgot all about this, far cleaner than the other approaches imho. – Andy Apr 4 '11 at 14:24
  • @dobeerman thanks for your answer. I tried doing this (showing nid instead of Title) and now I see in the select list: nid: ___ - Title: _____. What am I missing here? – Oscar Mederos Apr 4 '11 at 19:31
  • Also, I don't want it to show the field name, just the value – Oscar Mederos Apr 4 '11 at 19:32
  • @Oscar sounds like you have two fields (nid and title) and both are configured to display their label. Remove the title from the list of fields, and configure the remaining field (nid?) to have an empty label. – Andy Apr 5 '11 at 8:47
2

http://drupal.org/project/nodereference_explorer might be a bit overkill, it provides a selection dialog for node referencing and says "Plugin architecture for support of other CCK fields"

-1

if you just include the title in views, but you set it not to show, this works fine, and keeps title out.

//edit

"Is it possible to show in a select list, another field instead of the Title when referencing a node?" when using nodereference (apart of CCK) well from my own experience you can only use the default panel in a view to populate the nodereference dropdown - if you choose to just show the node title then fine - works great - but if you list a custom field from the node instead of title you will find it still appends the node title - so if you include the node title anyway and choose to not display it in the output, this gets around that - now re-reading the question I think OP was asking how to show custom fields - i missed that but this is useful for after he is showing the custom fields using views.

  • OP isn't actually asking this question in relation to Views. – Chapabu Oct 20 '12 at 16:24
  • see answer edit – codeguy Oct 20 '12 at 20:28

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.