3

In my page content type, I've created an entity reference field that references another page content. When entering data into the entity reference field, it does a search of all the content on the site and returns a list of it. I want to be able to just enter in the node ID, instead of making it search for it.

Currently, you cannot just put in the node ID, as it will throw an error about content not existing.

Is there a way to just input just the node ID? Is there a special format?

  • I hope there is some sort of a good reason for this, cause just having to put the nid is not user friendly. The person would've to know the nid of the node in advance. – No Sssweat Dec 15 '16 at 7:43
  • 5
    There is one trick that I often use on d.o as the autocomplete search can be slow due to the huge amount of nodes. The text must follow this pattern: "some text (ID)". If there is just "some text", it attempts to a 100% match on the title, but once you have (123) there, it ignores the text and just goes with 123. – Berdir Dec 15 '16 at 19:27
  • @NoSssweat i need this as a user is not going to manually input it. I have a js script that auto fills this out. i have the nid referenced elsewhere. – Patoshi パトシ Dec 15 '16 at 20:09
  • @Berdir Cool that works!!! If your nid is 45, you just put the following in the field: "blabhlabh (45)" --- make sure there is a SPACE between the words and the (45) or else it wont work! – Patoshi パトシ Dec 15 '16 at 20:16
3

There are a couple of options on how to do this.

1) switch the field settings reference method from "default" to "view", and create an entity reference view where the label is the nid

2) create a field widget plugin based on EntityReferenceAutocompleteWidget.php in your custom module, and replace the form element

'#type' => 'entity_autocomplete',

with a text field.

 '#type' => 'textfield',

Below is a custom widget that does this.

Most of the changes are within the formElement method, but I added some validation to check if the entity is a valid entity of the correct type within the allowed bundles.

namespace Drupal\mymodule\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\Validator\ConstraintViolationInterface;

/**
 * Plugin implementation of the 'entity_reference_textfield' widget.
 *
 * @FieldWidget(
 *   id = "entity_reference_textfield",
 *   label = @Translation("Textfield"),
 *   description = @Translation("A text field for entity reference"),
 *   field_types = {
 *     "entity_reference"
 *   }
 * )
 */
class EntityReferenceTextField extends WidgetBase  {

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    return array(
      'size' => '60',
      'placeholder' => '',
    ) + parent::defaultSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $element['size'] = array(
      '#type' => 'number',
      '#title' => t('Size of textfield'),
      '#default_value' => $this->getSetting('size'),
      '#min' => 1,
      '#required' => TRUE,
    );
    $element['placeholder'] = array(
      '#type' => 'textfield',
      '#title' => t('Placeholder'),
      '#default_value' => $this->getSetting('placeholder'),
      '#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'),
    );
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    $summary = array();

    $operators = $this->getMatchOperatorOptions();
    $summary[] = t('Textfield size: @size', array('@size' => $this->getSetting('size')));
    $placeholder = $this->getSetting('placeholder');
    if (!empty($placeholder)) {
      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
    }
    else {
      $summary[] = t('No placeholder');
    }

    return $summary;
  }

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {

    $values = $items->getValue();

    $element += array(
      '#type' => 'textfield',
      '#default_value' => isset($values[$delta]) ? $values[$delta]['target_id'] : NULL,
      '#size' => $this->getSetting('size'),
      '#placeholder' => $this->getSetting('placeholder'),
    );

    return array('target_id' => $element);
  }


  /**
   * {@inheritdoc}
   */
  public function errorElement(array $element, ConstraintViolationInterface $error, array $form, FormStateInterface $form_state) {

    if (empty($element['target_id'])) {
      return FALSE;
    }

    // Do some validation, to make sure this a real entity within
    // the list of allowed bundles.

    $settings = $this->getFieldSettings();

    $storage = \Drupal::entityTypeManager()->getStorage($settings['target_type']);

    $entity = $storage->load($element['target_id']['#value']);

    if (!empty($entity) && in_array($entity->bundle(), $settings['handler_settings']['target_bundles'])) {
      return $element['target_id'];
    }
    else {
      $form_state->setError($element['target_id'], t('This is not a valid entity reference id.'));
    }

    return FALSE;
  }

}
2

One quick solution without the need to code up anything is the following. This is only if you know the NID ahead of time either manually or programaticly. By default drupal autocomplete will try to search for it and the format will be like this once found:

This is My Node Title (76)

76 is the node id in this case. What you can do is just put any text before the (76) and it will work as the only thing you need is the (76). Like this:

asdfjalkdsfjldsjflkjdslkfjldsf (76)

Keep in mind you MUST have a SPACE between the text and the () or else it wont work!

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.