Score:0

Dynamicaly add ajax form item and add event on checkbox

kn flag

I've added an ajax callback to my form to add some data on it :

$form['add'] = [
    '#type' => 'button',
    '#value' => t('add'),
    '#ajax' => [
        'callback' => [$this, 'ajaxFormAdd'],
        'event' => 'click',
        'wrapper' => 'contacts',
        'progress' => [
            'type' => 'throbber',
            'message' => $this->t('Ajout d\'un contact...'),
        ],
    ],
];

This is how I render the new fields (they're appended into a specific div)

public function ajaxFormContact(array &$form, FormStateInterface $form_state) {
    /** @var \Drupal\Core\Ajax\AjaxResponse $response */
    $response = new AjaxResponse();

    $index = 0;
    $collapseId = 'collapse-contact-' . $index;
    $toggle = '<button class="btn btn-primary collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#' . $collapseId . '" aria-expanded="true" aria-controls="' . $collapseId . '">Contact ' . $index . '</button>';
    $collapse = '<div class="collapse show" id="' . $collapseId . '"><div class="card card-body"></div></div>';
    $contact = $this->buildSingleContact($index);
    $response->addCommand(new AppendCommand('#contacts', $toggle . $collapse));
    $response->addCommand(new AppendCommand('#' . $collapseId . ' > .card', $contact));
    $form_state->setRebuild();
    return $response;
}

And those are the fields added :

public function buildSingleContact(int $index) {
    $contact_single['contacts'][$index]['firstname'] = [
        '#type' => 'textfield',
        '#title' => 'firstname',
        '#attributes' => [
            'data-drupal-selector' => "edit-contacts-$index-firstname",
            'id' => "edit-contacts-$index-firstname",
            'name' => "contacts[$index][firstname]",
        ]
    ];
    $contact_single['contacts'][$index]['extraInfo'] = [
        '#type' => 'checkbox',
        '#title' => $this->t('Add info'),
        '#prefix' => '<div class="form-check form-switch">',
        '#suffix' => '</div>',
        '#attributes' => [
            'data-drupal-selector' => "edit-contacts-$index-extraInfo",
            'id' => "edit-contacts-$index-extraInfo",
            'name' => "contacts[$index][extraInfo]",
        ],
        '#ajax' => [
            'callback' => [$this, 'ajaxFormExtra'],
            'event' => 'change',
            'progress' => [
                'type' => 'throbber',
            ],
        ],
    ];
    return $contact_single;
}

So this is my problem:

The ajax on my button is working because the button is on the page when the page is loaded.

But the checkbox extraInfo has no event, because the contact is created after the js is loaded.

So how do I add the change event on my newly added checkboxes ? Is it possible to add like a "$(selector).on('click')" instead of "$(selector).click()" ?

No Sssweat avatar
ua flag
Does this answer your question? [Problem with Adding new fields with Ajax call to a custom form](https://drupal.stackexchange.com/questions/314343/problem-with-adding-new-fields-with-ajax-call-to-a-custom-form)
kn flag
Nop :) the problem on your link is that the input are not submitted, my problem is that the checkbox doesn't have the event because it's generated after the page is loaded
Score:1
cn flag

Nop :) the problem on your link is that the input are not submitted, my problem is that the checkbox doesn't have the event because it's generated after the page is loaded

When adding form elements too late in an ajax callback you're not only preventing input values to be submitted, but also you're bypassing the processing steps.

For a checkbox element these are:

  '#process' => [
    [$class, 'processCheckbox'],
    [$class, 'processAjaxForm'],
    [$class, 'processGroup'],

In your case you need processAjaxForm calling preRenderAjaxForm to attach the necessary JavaScript.

So add the form elements already in buildForm():

$form['contact'][$index] = $this->buildSingleContact($index);

Check $form_state->getTriggeringElement() for the right time to add the new fields.

The ajax callack is then only a delivery method for the dynamically added parts

$response->addCommand(new AppendCommand('#' . $collapseId . ' > .card', $form['contact'][$index]));

instead of the entire $form in a non-Ajax rebuild.

I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.