I am trying to edit the node creation form in order to add multiple 'tableselect' fields in it. My module adds options in a select field and add an ajax callback triggered by the 'change' event of that select. I want the ajax callback to return a new 'tableselect' field.

I have created a custom module and I do everything (hook + ajax callback) inside a mymodule.module file.

use \Drupal\Core\Form\FormStateInterface;

** Implement hook_form_alter

function pages_module_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
 if ($form_id == 'node_page_form') {
    $connection = \Drupal::database();

    $query = $connection->select('templates', 't');
    $query->fields('t', ['name', 'tid', 'components']);
    $result = $query->execute()->fetchAll();
    $form['select_template'] = array(
        '#type' => 'select',
        '#title' => t("Select a page template"),
        '#required' => true,
        '#field_suffix' => '<div id="dynamic-fields"></div>',
        '#ajax' => [
            'callback' => 'pages_module_mySelectChange',
            'event' => 'change',
            'wrapper' => 'dynamic-fields',
    foreach ($result as $template) {
        $form['select_template']['#options'][$template->tid] = $template->name;
function pages_module_mySelectChange(array $form, FormStateInterface $form_state)
$header = [
'first_name' => t('First Name'),
'last_name' => t('Last Name'),
$options = [
1 => [
'first_name' => 'Indy',
'last_name' => 'Jones',
2 => [
'first_name' => 'Darth',
'last_name' => 'Vader',
3 => [
'first_name' => 'Super',
'last_name' => 'Man',
$form['table1'] = array(
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options,

return $form['table1'];

My problem is that in order to create tableselect fields you have to be in a class that extends 'FormBase' and hooks can't be used in classes I believe. I'm a bit clueless about how to process in this case.

Maybe hooks can be used within classes ?

Maybe I don't need FormBase to create a tableselect field ?

Maybe I should separate my code in two parts, like calling a custom class method from my hook ?

Any help?

  • 1
    in order to create tableselect fields you have to be in a class that extends 'FormBase' Are you sure? I can’t imagine why that would be, table selects are just render arrays like any other. Could you explain a bit more what you mean by that? – Clive Sep 12 at 10:18
  • Separately, there’s one rule to understand about form Ajax callbacks - the callback is just there to return the element which should be displayed (or some Ajax commands). The actual adding or manipulating of an element needs to be done in the form builder, so either in a class that extends FormBase, or in the form alter hook, usually based on something in the form state – Clive Sep 12 at 10:20
  • I had indeed a bad understanding of what I should do and not do in ajax callback, thanks your comments helped me a lot ! – Hyco Sep 12 at 12:07

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.