Problem/Motivation
I'm trying to replace the link field on the core menu with an entity browser. But it's proving difficult to get good results. I have it so far as to display the "details" container and the "add entities" button. It opens a modal, displays the view, etc. But once I select entities from the view and it returns to the form it's not refreshing the form. I see the throbber image, but the form doesn't appear to be updated.
Upon looking at the page I can see the the entity id has been added, but it's been added to a generated hidden field instead of the target_id field I had created.
I modeled the render array after a node edit form entity browser widget.
Does anyone know how to get this to work?
Attached is my extremely long field definition. I'm pretty sure it's related to the naming on my divs, or including extra keys that don't need to be there. This is inside of a form_alter
.
$form['content_link'] = [
'#type' => 'container',
'#parents' => ['content_link_wrapper'],
'#weight' => -3,
'widget' => [
'#title' => t('Content Link'),
'#description' => t('The content to be linked in the menu.'),
'#field_name' => 'content_link',
'#field_parents' => [],
'#required' => TRUE,
'#parents' => ['content_link'],
'#tree' => TRUE,
'#id' => 'edit-content-link',
'#type' => 'details',
'#open' => TRUE,
'target_id' => [
'#type' => 'hidden',
'#id' => 'edit-content-link-target-id',
'#attributes' => [
'id' => 'edit-content-link-target-id',
],
'#default_value' => "",
'#ajax' => [
'callback' => [
'Drupal\entity_browser\Plugin\Field\FieldWidget\EntityReferenceBrowserWidget',
'updateWidgetCallback',
],
'wrapper' => 'edit-content-link',
'event' => 'entity_browser_value_updated',
],
],
'entity_browser' => [
'#type' => 'entity_browser',
'#entity_browser' => 'content_hub_page_browser',
'#cardinality' => 1,
'#selection_mode' => 'selection_append',
'#default_value' => [],
'#entity_browser_validators' => [
'entity_type' => [
'type' => 'node',
],
],
'#custom_hidden_id' => 'edit-content-link-target-id',
'#process' => [
[
'\Drupal\entity_browser\Element\EntityBrowserElement',
'processEntityBrowser',
],
[
'Drupal\entity_browser\Plugin\Field\FieldWidget\EntityReferenceBrowserWidget',
'processEntityBrowser',
],
]
],
'current' => [
'#theme_wrappers' => ['container'],
'#attributes' => [
'class' => 'entities-list',
],
'items' => [],
],
'#after_build' => [
[
'Drupal\entity_browser\Plugin\Field\FieldWidget\EntityReferenceBrowserWidget',
'afterBuild',
],
],
'#attached' => [
'library' => [
'entity_browser/entity_reference',
],
],
],
];
Comments
Comment #2
slashrsm CreditAttribution: slashrsm at MD Systems GmbH commentedEntity browser form element won't do any AJAX reloads for you. Only thing that it does is leaving entity ids of the selected entities in a hidden field. It is up to the form to figure out what to do with that from then on. Hidden element is added automatically and is not called target_id.
Then entity reference field widget that this module provides comes into the equation. It uses EB form element, but it does a bunch of other things too. It creates own hidden element and calls it "target_id". It also adds some JS code that catches the event of adding IDs to the hidden element and triggers AJAX reload based on that. You want to check how this things are done there. Specially: http://cgit.drupalcode.org/entity_browser/tree/src/Plugin/Field/FieldWid..., http://cgit.drupalcode.org/entity_browser/tree/js/entity_browser.entity_... and http://cgit.drupalcode.org/entity_browser/tree/js/entity_browser.common.js
Comment #3
slashrsm CreditAttribution: slashrsm at MD Systems GmbH commentedComment #5
lykyd CreditAttribution: lykyd commentedSo how do we add Entity Browser widget to custom form ???
Comment #6
DiDebruWould interest me too.
Comment #7
woprrr CreditAttribution: woprrr as a volunteer and at NeoLynk commented@Insasse your can with usage of entity_browser form element available LIKE :
Or more complexe :
Comment #8
DiDebruThank you @woprr.
Comment #9
simeI think this information is stale, or something changed in the module. It would be great to formalise this technique in a working example. This is what I have so far to add entity browser to the "add link" form on a menu. It doesn't seem to support cardinality properly, and I have not looked at why the value does not "stick" on the form after selection.
Comment #10
RAFA3L CreditAttribution: RAFA3L commentedSame problem here, the file don't appear after select it
Comment #11
RAFA3L CreditAttribution: RAFA3L commentedThe trick to show the image after select it is adding a custom function like displayCurrentSelection in the entity_browser module. This private function is responsible for displaying the list of files and is not called in any way from a custom widget.
Here is the code with the custom the displayCurrentSelection passing the file id to generate the html markup with the image, basically it should be inside the ajax wrapper id:
Comment #12
ravi.sidd CreditAttribution: ravi.sidd commentedNobody is able to understand how to integrate entity browser, select an image and then show the image. Please help.
Comment #13
bingelis CreditAttribution: bingelis commentedLanded here, in one of the threads issuing the same usage of entity_browser problem in custom forms, and none provides a complete solution/example. Here is what I came to after dealing with the problem.
Appending code in @RAFA3L comment, just basic method in your class of custom form to define representation for selection (i.e. show selected file name, but you could implement something more advanced):
FIle name got shown up, but only once, not updated when wanted to replace ir with different file.
This behavior relates to incompatible properties of 'entity_browser' element:
Staying with '#cardinality' => 1, one should used '#selection_mode' => 'selection_edit', but for me it resulted in php error "Used entity browser selection display does not support preselection". If you manage, use selection display which supports preselection, but here's my workaround. Firstly, edit ajax callback of 'target_id'
'callback' => [get_class($this), 'updateWidgetCallback'],
And define own callback method in custom form class:
Comment #14
bingelis CreditAttribution: bingelis commentedLanded here, in one of the threads issuing the same usage of entity_browser problem in custom forms, and none provides a complete solution/example. Here is what I came to after dealing with the problem.
Appending code in @RAFA3L comment, just basic method in your class of custom form to define representation for selection (i.e. show selected file name, but you could implement something more advanced):
FIle name got shown up, but only once, not updated when wanted to replace ir with different file.
This behavior relates to incompatible properties of 'entity_browser' element:
Staying with '#cardinality' => 1, one should used '#selection_mode' => 'selection_edit', but for me it resulted in php error "Used entity browser selection display does not support preselection". If you manage, use selection display which supports preselection, but here's my workaround. Firstly, edit ajax callback of 'target_id'
'callback' => [get_class($this), 'updateWidgetCallback'],
And define own callback method in custom form class:
Comment #15
bingelis CreditAttribution: bingelis commentedLanded here, in one of the threads issuing the same usage of entity_browser problem in custom forms, and none provides a complete solution/example. Here is what I came to after dealing with the problem.
Appending code in @RAFA3L comment, just basic method in your class of custom form to define representation for selection (i.e. show selected file name, but you could implement something more advanced):
FIle name got shown up, but only once, not updated when wanted to replace ir with different file.
This behavior relates to incompatible properties of 'entity_browser' element:
Staying with '#cardinality' => 1, one should used '#selection_mode' => 'selection_edit', but for me it resulted in php error "Used entity browser selection display does not support preselection". If you manage, use selection display which supports preselection, but here's my workaround. Firstly, edit ajax callback of 'target_id'
'callback' => [get_class($this), 'updateWidgetCallback'],
And define own callback method in custom form class:
Comment #16
bingelis CreditAttribution: bingelis commentedamadady@gmail.com, you should implement representation for selection.
Just basic example to show selected filename:
Similar approach would be to show media thumbnail according your needs.
Comment #17
oknateRe-opening this. I have also tried to do this in the past and it was painful.
Ideally there'd be a way to include the current selection in the stand-alone element, thereby providing ajax buttons as well as a display of the currently selected items.
Comment #18
PrineShazar CreditAttribution: PrineShazar commented+1
This is very much needed. Lots of scenarios where users may not want to navigate to a node edit form, and so may want to edit existing nodes inline from a convenient place.
Comment #19
Dave ReidAgreed, being able to easily and independently use the entity browser FAPI element seems like we need a lot of wrapping boilerplate that would be either good to have an example documented or provide some of the boilerplate by default.
Comment #20
Thomas.Schnitzler CreditAttribution: Thomas.Schnitzler commentedI got a mix of RAFA3Ls and Bigelis' solutions up and running, but this has a major drawback: The default functions for the preview items do not work. E.g.:
Any hope, that this will get any boilerplate code or detailed documentation?
Comment #21
Dave ReidI ended up abstracting some of the code from Entity Browser Block into a Helper module EntityBrowserFormTrait so I could re-use it for form and plugins-with-forms classes. Feel free to file issues with requests An example usage in a block plugin form:
Comment #22
paul_leclerc CreditAttribution: paul_leclerc commentedThanks #21 :)
I use your Trait, but I had to replace
$entity_ids = $form_state->getValue(array_merge($parents, ['browser', 'entity_ids']), '');
by
$entity_ids = $form_state->getValue('browser')['entity_ids'];
I still need to understand why it didnt work and make some more dynamic or using shared var.
And we had some code to allow multi fields.
We could push a MR to your Trait if we want.
Comment #23
PrineShazar CreditAttribution: PrineShazar commentedThanks Dave!
Comment #24
Yasser Samman#21 + #22 saved my life..
Comment #25
lapaty CreditAttribution: lapaty commentedThanks Dave #21 Saved my life too!! ;)
Comment #26
Joao Sausen CreditAttribution: Joao Sausen commented#21 fixed it too, but a better fix is to add
"#tree" => TRUE,
to the $element in the getEntityBrowserForm method.Comment #27
arnaud-brugnon CreditAttribution: arnaud-brugnon commented#21 works for me in custom form only if we had #tree = TRUE
Comment #28
florianmuellerCHThank you all for your work! #21 and the info in #22 helped me a lot!
I added a JS behavior to make the selected elements sortable. To do that I had to add my library and a class in the base element:
Be sure to add the dependency to
core/sortable
in your libraries.yml.Comment #29
gnuget#21 worked for me too.
Thanks!!!
Comment #30
tlo405 CreditAttribution: tlo405 commentedI've been using the code in #21 for a while on my site and it has worked great! I had a custom ckeditor plugin that opened up a modal that contained a few form fields, one of which needed to open our custom entity browser. However, I've been attempting to upgrade to ckeditor5, and I can not get this functionality to work any longer.
Clicking the button on the ckeditor5 toolbar opens up my modal successfully, and my other fields work...but I can't get the custom entity browser field to work correctly. Once I make a selection, I still see a 'No items selected yet' message. I would expect the image that I selected to appear there. Even if I hardcode
media:123
for example as the default value, I still see the 'no items selected yet' message.Just wondering if anyone has seen a similar issue? I really don't know what could be causing this to happen.