I am building a form in Drupal 8 that contains a sortable jQuery accordion.
I have the accordion working and am able to add new elements to the accordion utilizing a submit button with an AJAX callback. However, when I reorder the elements in the accordion and then add a new element, the order of the accordion reverts to the original. I have a hidden field for each element in the accordion to store the order in and would like to rebuild the form based on these values, however I am at a loss for how to send this back to Drupal from the Javascript.
I have reviewed some examples like here: Send data from JavaScript to Controller for how to use AJAX to send back to Drupal, however every example I see involves sending back to a menu item, not a form. This is the missing link for me, any help with how I can complete the linkage back to the form is much appreciated.
Here is the routing yml file:
mymodule:
path: /mymodule
defaults:
_form: '\Drupal\mymodule\Form\ContributeForm'
requirements:
_permission: 'access content'
Here is a portion of the Drupal form code, including all of it is overwhelming:
$dataArray = array();
// Loop through existing fields
for ($i = 0; $i < $name_field_init; $i++) {
for($j = 0; $j < $name_field_init; $j++){
if($i == $form_state->getCompleteForm()['wrapper']['accordion']["container$j"]["sort_order$j"]['#value']){
foreach ($form_state->getValues()['wrapper']['accordion']["container$j"] as $key => $value) {
$dataArray[$i][$key] = $value;
}
}//if
}//for j
}//for i
$i = 0;
foreach($dataArray AS $row){
$dataVal = "test$i";
$form['wrapper']['accordion']["container$i"] = array(
'#type' => 'container',
'#id' => "container_$i",
'#name' => $i,
'#attributes' => array(
'class' => array(
'container_l_01',
),
),
);
$form['wrapper']['accordion']["container$i"]["sort_order$i"] = array(
'#type' => 'hidden',
'#value' => $i,
'#attributes' => array(
'class' => array(
'sort-order',
),
),
);
$form['wrapper']['accordion']["container$i"]["title$i"] = array(
'#markup' => "<h3>$dataVal</h3>",
);
$form['wrapper']['accordion']["container$i"]["textbox$i"] = array(
'#type' => 'textfield',
'#title' => "$dataVal field",
'#default_value' => $row["textbox$i"],
);
$i++;
}//foreach
Here is the javascript:
(function ($) {
'use strict';
Drupal.behaviors.mymodule = {
attach: function(context, settings) {
$(document).ready(function () {
$('#accordion').accordion({
collapsible: true,
active: false,
height: 'fill',
header: 'h3'
}).sortable({
items: '.container_l_01',
stop: function(event, ui) {
var data = "";
$(".container_l_01").each(function(i, el){
data += $(el).attr('id') + '=' + $(el).children('.sort-order').val() + ',';
});
alert(data);
}
});
$('#accordion').on('accordionactivate', function (event, ui) {
if (ui.newPanel.length) {
$('#accordion').sortable('disable');
}
else {
//alert("entered the else");
$('#accordion').sortable('enable');
}
});
});
}
}
})(jQuery);