I've created a module which defines a Form, but when I try to add a column of links, it is empty when I set the '#type'
to 'link'
. I am testing this on Drupal 9.3.x.
On the surface, this is the same as Add a link to a tableselect row, but the answer posted there does not contain the full working code, and I'm fairly sure the solution in my context is going to differ from the one posted there.
This is the full code of the class which extends FormBase
.
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class MyForm extends FormBase {
public function buildForm(array $form, \Drupal\Core\Form\FormStateInterface $form_state) {
// Build the fileNameOptions
$privatePath = 'private://webform/upload/';
$linkPath = '/system/files/webform/upload/';
$templatePath = \Drupal::service('file_system')->realpath($privatePath);
$fileList = glob($templatePath.'/*');
$fileNameOptions = [];
$pathLength = strlen($templatePath);
foreach ($fileList as $filePath) {
$fileName = substr($filePath, $pathLength + 1);
$fileNameOptions[$fileName] = [
'filename' => $fileName,
'link' => [
'data' => [
'#type' => 'link',
'#url' => $linkPath . $fileName,
'#title' => $fileName,
],
],
];
}
//Build the tableSelect.
$form['templates'] = [
'#type' => 'tableselect',
'#header' => ['filename' => 'File name', 'link' => 'Link'],
'#options' => $fileNameOptions,
'#empty' => t('No files were found.'),
'#weight' => 40,
'#js_select' => FALSE,
];
return $form;
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'my_form';
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);
}
}
For some context, this form is attempting to show the admin a list of private files uploaded from webforms, plus links enabling them to inspect each file. The intent is to use the tableselect
to allow the admin to delete unwanted files. I understand that there are security implications, and that this form should only be accessible to trusted admins. Showing the list of files works, and I'm fairly sure I can get the file deletion working. I have a webform which displays the links correctly, but it would be a better user experience if the deletion form also allows the admin to view the files through links.
If I change the '#type'
of the link field from 'link'
to 'textfield'
or 'textarea'
, the column contains the elements I would expect - the title followed by a textfield or textarea. When I change the '#type'
back to 'link'
(as shown in the code above), the column is completely empty. When I view the page source, that column contains empty <td>
tags.
<td></td>
It's exactly the same as if I change the '#type'
to 'foo'
. This implies to me that the 'link'
field type is not available in the context of this form. To test this, I tried to adapt How do I get all available form field types? to the Drupal 9 context.
$all_types = \Drupal::moduleHandler()->invokeAll('hook_elements');
\Drupal::messenger()->addMessage(json_encode($all_types));
However, hook_elements()
doesn't seem to be used any more, so this doesn't work.
Form and render elements shows 'link'
as a valid render element in Drupal 9.4.x, so my understanding is that it should be available in forms created by a custom module.
CommentAdminOverview::buildForm()
shows a very similar use of '#type' => 'link'
.
My reading of the existing answer is that the problem there was that the column was not added to the '#header'
array (not visible in the code posted).
- Have I missed some simple detail in the code I've posted above, which causes
'link'
fields to be empty, while changing the '#type'
to 'textfield'
produces the expected result?
- Is there some way to verify the set of valid
'#type'
strings in my context?
- If the
'link'
field type is not available in my context, how can I make it available?
Nothing is added to the Drupal log when I load this form.