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;
}
}