Would it be possible by using a behavior plugin to extend the entityreference field with another textfield?

Comments

SebCorbin’s picture

Issue summary: View changes

Updated issue summary.

Andre-B’s picture

Issue summary: View changes

anything on this?

SebCorbin’s picture

Status: Active » Fixed

First, create a behavior:

/**
 * Implements hook_ctools_plugin_directory().
 */
function mymodule_ctools_plugin_directory($module, $plugin) {
  if ($module === 'entityreference') {
    return 'plugins/' . $plugin;
  }
}

And create a directory behavior within another named plugins. Add a file name for exemple your_field.inc in it:


$plugin = array(
  'title' => t('Add a textfield to the reference'),
  'class' => 'YourFieldBehavior',
  'behavior type' => 'field',
);

And add a file in the same behavior directory named after the plugin, YourFieldBehavior.class.php:


/**
 * Class YourFieldBehavior
 */
class YourFieldBehavior extends EntityReference_BehaviorHandler_Abstract {

  /**
   * Alter the schema to add our field
   *
   * @param $schema
   * @param $field
   */
  public function schema_alter(&$schema, $field) {
    $schema['columns']['yourfield'] = array(
      'description' => 'A label for the reference.',
      'type'        => 'varchar',
      'length'      => 255,
      'default'     => 0,
      'not null'    => TRUE,
    );
  }
}

The schema part is now done, flush the caches and the behavior should appear in the entityreference field settings.

Now we need to alter the widget, return to mymodule.module:

/**
 * Implements hook_field_widget_form_alter().
 */
function mymodule_field_widget_form_alter(&$element, &$form_state, $context) {
  // Act on our behavior.
  if (!empty($context['field']['settings']['handler_settings']['behaviors']['your_field']['status'])) {
    $element['yourfield'] = array(
      '#type'     => 'textfield',
      '#title'    => 'My label',
      '#weight'   => -1,
      '#required' => TRUE,
    );
    $element['target_id']['#title'] = 'My reference';
  }
}

Yup that's it, the textfield will be saved along with the reference!

You may want to add it to the display:


/**
 * Implements hook_field_attach_view_alter().
 */
function mymodule_field_attach_view_alter(&$output, $context) {
  // Prefix the reference with the label.
  foreach (element_children($output) as $field_name) {
    $element = &$output[$field_name];
    if ($element['#field_type'] == 'entityreference') {
      $field = field_info_field($field_name);
      if (!empty($field['settings']['handler_settings']['behaviors']['your_field']['status'])) {
        foreach ($element['#items'] as $delta => $item) {
          $element[$delta]['#prefix'] = "<strong>{$item['yourfield']} :</strong> ";
        }
      }
    }
  }
}

Now maybe this should be added to the documentation?

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

dgtlmoon’s picture

Status: Closed (fixed) » Needs work

I'de like to re-open this issue because it appears that the above approach only works correctly when the widget is of type 'autocomplete', using 'select' widget the $element structure that is passed-in doesn't seem to allow extra fields to be appended to its array in such a fashion - they are ignored

Andre-B’s picture

I got an implementation here as well: https://www.drupal.org/sandbox/baumeier.it/2078043 I did not diff my with the one provided in #2 though

arcaic’s picture

I have been trying to do this with no success.....

I have implemented the code of SebCorbin and got the behaviors working in that I can create an entity reference in a content type, select the behavior (and have its settings form displayed), I can see the schema_alter firing and I can create a node and enter the text in the text field I've added (employee_name) and choose a node for the reference.

Problem is nothing is saved. No errors no nothing. Not even the node reference is saved.

Thing is I don't really understand how or where the data I enter in my text field is supposed to get saved. Schema alter for the behavior doesn't actually modify the database, right? If correct then where should I add the code that modifies the database table for the created fields?

Ideally I would have thought it should be done when the behavior is chosen when the field is created or at the very least when the field is saved. How to do this though?

My use case is to allow a user to select a node reference from a content type of employee but if the employee is not on the site allow their name as text instead.

Any help would be much appreciated.

Many thanks

Andy