I have a custom entity (contract_subscription) created in a custom module (amap) by a bunch of BaseFieldDefinition, one of which being a file field:

$fields['file'] = BaseFieldDefinition::create('file')
  ->setLabel(t('pdf file'))
    'target_type' => 'file',
    'file_extensions' => 'pdf',
    'uri_scheme' => 'private',
    'file_directory' => 'contracts/subscriptions',

I created a form to "mass"update this entity.
In this form, the file field is defined this way:

$form['subscriptions'][$key]['file'] = array(
    '#type' => 'managed_file',
    '#upload_validators' => array(
      'file_validate_extensions' => array('pdf'),

wich gives this:
enter image description here I'd like to replace the standard way the file field is presented by a simple button.
The click on the button would show a modal popup with the standard file field management in it.
How can I do that?

I updated my code this way.
Replaced the file field by a link and a hidden field:

  $form['subscriptions'][$key]['filelink'] = array(
    '#type' => 'link',
    '#title' => $title,
    '#url' => Url::fromRoute('amap.contract_subscription_file_form', ['file' => $fileId]),
    '#attributes' => [
      'id' => ['myLink' . $key],                     <-- New
      'class' => ['use-ajax'],
      'data-dialog-type' => 'modal',

  $form['subscriptions'][$key]['file'] = array(
  '#type' => 'hidden',
  '#attributes' => array('id' => 'myFile' . $key),   <-- New
  '#default_value' => $fileId,

Added this to amap.routing.yml

  path: '/amap/contract/subscription/{file}'
    _form: '\Drupal\amap\Form\ContractSubscriptionFileForm'
    _title: 'Add file'
    _access: 'TRUE' 

and this ContractSubscriptionFileForm definition:

class ContractSubscriptionFileForm extends FormBase
  public function getFormId()
    return 'contract_subscription_file_form';

  public function buildForm(array $form, FormStateInterface $form_state, $file = NULL)
    $form['file'] = array(
      '#type' => 'managed_file',
      '#upload_location' => 'private://contracts/subscriptions/',
      '#upload_validators' => array(
        'file_validate_extensions' => array('pdf'),
      '#default_value' => array($file),
    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
      '#ajax' => [
        'callback' => '::ajaxSubmitForm',
        'event' => 'click',
    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';
    return $form;

  public function validateForm(array &$form, FormStateInterface $form_state)
    parent::validateForm($form, $form_state);

  public function submitForm(array &$form, FormStateInterface $form_state)

  public function ajaxSubmitForm(array &$form, FormStateInterface $form_state)
    $response = new AjaxResponse();
    $html = '<a href="/amap/contract/subscription/999" id="myLink1" class="use-ajax" data-dialog-type="modal" data-drupal-selector="edit-subscriptions-0-filelink">999</a>';
    $response->addCommand(new ReplaceCommand('#myLink1', $html));
    $html = '<input data-drupal-selector="myFile1" type="hidden" name="subscriptions[1][file]" value="999">';
    $response->addCommand(new ReplaceCommand('#myFile1', $html));
    $response->addCommand(new CloseModalDialogCommand());
    return $response;

And now I get:
enter image description here when the file already exists
enter image description here when there is no file

The $html code in ajaxSubmitForm is hardcoded only for test purpose...
When I submit the modal, the original table form is updated accordingly (the link title = 999 and the link URI points to .../999.

My question is: I can get the value of file id from $form_state and replace the 999of my current code.
But I don't know how to retrieve the generated html for myLink1 and myFile1.
Any idea?

  • You probably don’t need anything Drupal-y for that - if you’ve already got the markup in the page, there are tons of libraries out there you can use to display the elements in a modal – Clive Apr 11 at 17:40
  • If you can modify the html of the output try this drupal.stackexchange.com/questions/249040/… sollution is not webform specific – GiorgosK Apr 11 at 17:52
  • The problem with doing it that way is you need a new form (or form mode), a route to get it from, etc @GiorgosK. Might be easier just to use some js if the content is already there – Clive Apr 11 at 18:03
  • @clive you are right I did not read the question carefully, I thought it was just for display – GiorgosK Apr 11 at 18:09
  • @Clive any examples I could look at? – gbmapo Apr 12 at 11:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.