I've been trying to build a form referencing an entity using an entity reference view. The general purpose is to allow more fine-grained filtering for this form and other module forms than supplied by the standard entity_reference handler, without having to build a plugin or use hook_query_alter.  Though I am definitely open to such suggestions (esp. with pointers to good detailed documentation) - I am using entities and it seems some such docs are for nodes.

Here's the methodology I followed so far, with some notes along the way.

I created a target entity ("my_target") and a test content type ("test").  Created a view ("test_view") and an entity reference display for it ("entity_reference_1"), added a field to "test" of type entity reference which uses view "test_view" for the form element.

Put a hook_form_alter targeting the edit form in a module which dumps the $form output - either with kint() or dump().

Took the kint() output of the element - $form['tester'].

In the created form - this does not even display.  I'd appreciate any tips on getting this to work.

Some thoughts first: 

a.) It's a bit weird that this makes the form element #type 'container' containing a #widget array, with the basic element config as the first element of #widget.

b.) dump() output was very different from kint().  Dump did not have any mention of the view or the view display; I saw no evidence of any form handling info except for in #after_build array, which pointed to Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteWidget - I had no idea how the form builder knew from this info to use the views handler, or which view to grab.  That's why I built the element on the basis of the kint() output.

c.) Having some good documentation in the form of a tutorial on how to do this would be a great asset to the Drupal community.  Views is a very nice shortcut for getting custom selectors of existing content for entity references.

d.) This is just a very simple view limiting the entities selectable to those the user created / owns.  But this same functionality will be quite powerful with the addition of views arguments, which I will probably need to be employing down the line somewhere.

e.) What would also be tremendously handy - and I think value to the Drupal community - is info on putting such in entity BaseFieldDefinitions. Such information quite valuable.

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $oid = NULL) {
	$form['oid'] = array(
		'#type' => 'number',
		'#title' => t('Outline id (oid)'),
		'#required' => TRUE,
		'#default_value' => $oid,
	);
	
	$form['tester'] = array(
	'#type'=>'container',
	'#title' => 'Testing element',
	'#widget'=> array(
		0 => array(
			'target_id' => array(
				'#title' => 'Testing Element',
				'#type' => 'entity_autocomplete',
				'#target_type' => 'my_target',
				'#selection_handler' => 'views',
				'#selection_settings' => array(
					'view' => array(
						'view_name' => 'test_view',
						'display_name' => 'entity_reference_1',
						'arguments' => array(),
					),
				),
				'#default_value' => \Drupal::entityTypeManager()->getStorage('my_target')->load(1),
			),
		),
	),
	);
	
	$form['parent_id'] = array(
		'#type' => 'number',
		'#title' => t('Parent id (oid) of outline element - only for adding info to existing outline'),
		'#required' => FALSE,
	);
	
	$form['data_input'] = array(
		'#type' => 'textarea',
		'#title' => t('Data input'),
		'#required' => TRUE,
	);
	
	$form['submit'] = array(
		'#type' => 'submit',
		'#title' => 'submit',
	);
  
	return $form;
  }

Comments

jmcoder2’s picture

Progress on this issue -

I've been trying to capture the form build array with the following code:

	  $values = array('type' => 'test');

		$node = \Drupal::entityTypeManager()
		  ->getStorage('node')
		  ->create($values);

		$form = \Drupal::entityTypeManager()
		  ->getFormObject('node', 'default')
		  ->setEntity($node);
		$content = \Drupal::formBuilder()->getForm($form);

This renders the form nicely when it's simply returned by the controller from one of the routing destination methods - but it's a huge array.  

jasonglisson’s picture

I'm building a form contained within a module and need to load an entity reference field from the module. The field already exist in the user registration form, so I need to reuse that field. Though, nothing I have tried seems to work. I can kint out all of the data I need but I can't get the entity reference field to render at all.