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'))
->setSettings([
'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:
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?
[Edit]
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
amap.contract_subscription_file_form:
path: '/amap/contract/subscription/{file}'
defaults:
_form: '\Drupal\amap\Form\ContractSubscriptionFileForm'
_title: 'Add file'
requirements:
_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:
when the file already exists
when there is no file
[Edit2]
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 999
of my current code.
But I don't know how to retrieve the generated html for myLink1
and myFile1
.
Any idea?