diff --git a/ajax_example/ajax_example.info.yml b/ajax_example/ajax_example.info.yml index b02c330..866e240 100644 --- a/ajax_example/ajax_example.info.yml +++ b/ajax_example/ajax_example.info.yml @@ -4,4 +4,5 @@ description: 'An example module showing how to use Drupal AJAX forms.' package: 'Example modules' core: 8.x dependencies: + - core:node - drupal:examples diff --git a/ajax_example/ajax_example.links.menu.yml b/ajax_example/ajax_example.links.menu.yml index 2e50105..914d35b 100644 --- a/ajax_example/ajax_example.links.menu.yml +++ b/ajax_example/ajax_example.links.menu.yml @@ -1,7 +1,8 @@ ajax_example.description: title: 'AJAX Example' route_name: 'ajax_example.description' - weight: 10 + expanded: TRUE + ajax_example.simplest: title: 'Simplest AJAX Example' route_name: 'ajax_example.simplest' @@ -27,14 +28,14 @@ ajax_example.dependent-dropdown: route_name: 'ajax_example.dependent_dropdown' parent: ajax_example.description -ajax_example.dependent-dropdown-degardes: - title: 'Dependent dropdown degardes' - route_name: 'ajax_example.dependent_dropdown_degardes' +ajax_example.dependent-dropdown-degrades: + title: 'Dependent dropdown degrades' + route_name: 'ajax_example.dependent_dropdown_degrades' parent: ajax_example.description -ajax_example.dependent-dropdown-degardes-nojava: - title: 'Dependent dropdown degardes w/JS turned off ' - route_name: 'ajax_example.dependent_dropdown_degardes_nojava' +ajax_example.dependent-dropdown-degrades-nojava: + title: 'Dependent dropdown degrades w/JS turned off ' + route_name: 'ajax_example.dependent_dropdown_degrades_nojava' parent: ajax_example.description ajax_example.dynamic-dropdown: @@ -42,7 +43,7 @@ ajax_example.dynamic-dropdown: route_name: 'ajax_example.dynamic_sections' parent: ajax_example.description -ajax_example.dynamic-dropdown-degardes-nojava-example: +ajax_example.dynamic-dropdown-degrades-nojava-example: title: 'Dynamic Sections (with graceful degradation) w/js turned off' route_name: 'ajax_example.dynamic_sections_nojava' parent: ajax_example.description diff --git a/ajax_example/ajax_example.routing.yml b/ajax_example/ajax_example.routing.yml index 39c12bb..45d435b 100644 --- a/ajax_example/ajax_example.routing.yml +++ b/ajax_example/ajax_example.routing.yml @@ -4,7 +4,7 @@ ajax_example.description: _controller: '\Drupal\ajax_example\Controller\AjaxExampleController::description' _title: 'AJAX Example' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.simplest: path: 'examples/ajax-example/simplest' @@ -12,7 +12,7 @@ ajax_example.simplest: _form: '\Drupal\ajax_example\Form\AjaxExampleSimplest' _title: 'Simplest AJAX Example' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.progresssbar: path: 'examples/ajax-example/progressbar' @@ -20,7 +20,7 @@ ajax_example.progresssbar: _form: '\Drupal\ajax_example\Form\AjaxExampleProgressBar' _title: 'Progress bar' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.progresssbarProgress: path: 'examples/ajax_example/progressbar/progress/{time}' @@ -30,7 +30,7 @@ ajax_example.progresssbarProgress: # We provide default value to both arguments. time: '' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.autocheckboxes: path: 'examples/ajax-example/autocheckboxes' @@ -38,7 +38,7 @@ ajax_example.autocheckboxes: _form: '\Drupal\ajax_example\Form\AjaxExampleAutocheckboxes' _title: 'Generate checkboxes' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.autotextfields: path: 'examples/ajax-example/autotextfields' @@ -46,7 +46,7 @@ ajax_example.autotextfields: _form: '\Drupal\ajax_example\Form\AjaxExampleAutotextfields' _title: 'Generate textfields' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.submit-driven-ajax: path: 'examples/ajax-example/submit-driven-ajax' @@ -54,7 +54,7 @@ ajax_example.submit-driven-ajax: _form: '\Drupal\ajax_example\Form\AjaxExampleSubmitDriven' _title: 'Submit-driven AJAX' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.dependent_dropdown: path: 'examples/ajax-example/dependent-dropdown' @@ -62,41 +62,41 @@ ajax_example.dependent_dropdown: _form: '\Drupal\ajax_example\Form\AjaxExampleDependentDropdown' _title: 'Dependent dropdown' requirements: - _access: 'TRUE' + _permission: 'access content' -ajax_example.dependent_dropdown_degardes: - path: 'examples/ajax-example/dependent-dropdown-degardes' +ajax_example.dependent_dropdown_degrades: + path: 'examples/ajax-example/dependent-dropdown-degrades' defaults: - _form: '\Drupal\ajax_example\Form\AjaxExampleDependentDropdownDegardes' - _title: 'Dependent dropdown degardes' + _form: '\Drupal\ajax_example\Form\AjaxExampleDependentDropdownDegrades' + _title: 'Dependent dropdown degrades' requirements: - _access: 'TRUE' + _permission: 'access content' -ajax_example.dependent_dropdown_degardes_nojava: - path: 'examples/ajax-example/dependent-dropdown-degardes-nojava/{no_js_use}' +ajax_example.dependent_dropdown_degrades_nojava: + path: 'examples/ajax-example/dependent-dropdown-degrades-nojava/{no_js_use}' defaults: - _form: '\Drupal\ajax_example\Form\AjaxExampleDependentDropdownDegardes' - _title: 'Dependent dropdown degardes w/JS turned off ' + _form: '\Drupal\ajax_example\Form\AjaxExampleDependentDropdownDegrades' + _title: 'Dependent dropdown degrades w/JS turned off ' no_js_use: TRUE requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.dynamic_sections: path: 'examples/ajax-example/dynamic-sections' defaults: - _form: '\Drupal\ajax_example\Form\AjaxExampleDynamicSectionsDegardes' + _form: '\Drupal\ajax_example\Form\AjaxExampleDependentDropdownDegrades' _title: 'Dynamic Sections (with graceful degradation)' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.dynamic_sections_nojava: path: 'examples/ajax-example/dynamic-sections-nojava/{no_js_use}' defaults: - _form: '\Drupal\ajax_example\Form\AjaxExampleDynamicSectionsDegardes' + _form: '\Drupal\ajax_example\Form\AjaxExampleDynamicSectionsDegrades' _title: 'Dynamic Sections w/JS turned off' no_js_use: TRUE requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.wizard: path: 'examples/ajax-example/wizard' @@ -104,7 +104,7 @@ ajax_example.wizard: _form: '\Drupal\ajax_example\Form\AjaxExampleWizard' _title: 'Wizard (with graceful degradation)' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.wizardnojs: path: 'examples/ajax-example/wizard-nojs/{no_js_use}' @@ -113,7 +113,7 @@ ajax_example.wizardnojs: _title: 'Wizard (with graceful degradation) w/JS turned off' no_js_use: TRUE requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.addmore: path: 'examples/ajax-example/add-more' @@ -121,7 +121,7 @@ ajax_example.addmore: _form: '\Drupal\ajax_example\Form\AjaxExampleAddMore' _title: 'Add more button (with graceful degradation)' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.addmorenojs: path: 'examples/ajax-example/add-more-nojs/{no_js_use}' @@ -130,7 +130,7 @@ ajax_example.addmorenojs: _title: 'Add more button (with graceful degradation) w/JS turned off' no_js_use: TRUE requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.advanced: path: 'examples/ajax-example/advanced-commands' @@ -138,7 +138,7 @@ ajax_example.advanced: _form: '\Drupal\ajax_example\Form\AjaxExampleAdvancedCommands' _title: 'AJAX framework commands' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.Ajaxlink: path: 'examples/ajax-example/ajax-link' @@ -146,7 +146,7 @@ ajax_example.Ajaxlink: _controller: '\Drupal\ajax_example\Controller\AjaxExampleController::ajaxExampleRenderLink' _title: 'Ajax Link (Renderable Array)' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.Ajaxlinkrender: path: 'examples/ajax-example/ajax-link-renderable' @@ -154,12 +154,12 @@ ajax_example.Ajaxlinkrender: _controller: '\Drupal\ajax_example\Controller\AjaxExampleController::ajaxExampleRenderLinkRa' _title: 'Ajax Link (Renderable Array)' requirements: - _access: 'TRUE' + _permission: 'access content' ajax_example.Ajaxlinkcall: path: 'ajax_link_callback' defaults: - _controller: '\Drupal\ajax_example\Controller\AjaxExampleController::ajaxlinkresponse' + _controller: '\Drupal\ajax_example\Controller\AjaxExampleController::ajaxLinkResponse' requirements: _permission: 'access content' @@ -174,14 +174,14 @@ ajax_example.AutocompleteSimplest: ajax_example.AutocompleteSimplestcallback: path: 'examples/ajax_example/simple_user_autocomplete_callback' defaults: - _controller: '\Drupal\ajax_example\Controller\AjaxExampleController::ajax_example_simple_user_autocomplete_callback' + _controller: '\Drupal\ajax_example\Controller\AjaxExampleController::simpleUserAutocompleteCallback' requirements: _permission: 'access user profiles, access content' ajax_example.Autocompletenode: path: 'examples/ajax_example/node_autocomplete' defaults: - _form: '\Drupal\ajax_example\Form\AjaxExampleUniquecomplete' + _form: '\Drupal\ajax_example\Form\AjaxExampleUniqueComplete' _title: 'Autocomplete (node with nid)' requirements: _permission: 'access content' @@ -189,6 +189,6 @@ ajax_example.Autocompletenode: ajax_example.Autocompletenodecallback: path: 'examples/ajax_example/unique_node_autocomplete_callback' defaults: - _controller: '\Drupal\ajax_example\Controller\AjaxExampleController::ajax_example_unique_node_autocomplete_callback' + _controller: '\Drupal\ajax_example\Controller\AjaxExampleController::uniqueNodeAutocompleteCallback' requirements: _permission: 'access content' diff --git a/ajax_example/src/Controller/AjaxExampleController.php b/ajax_example/src/Controller/AjaxExampleController.php index 356d199..6ad8a18 100644 --- a/ajax_example/src/Controller/AjaxExampleController.php +++ b/ajax_example/src/Controller/AjaxExampleController.php @@ -2,37 +2,47 @@ namespace Drupal\ajax_example\Controller; +use Drupal\Component\Utility\SafeMarkup; +use Drupal\Core\Ajax\AjaxResponse; +use Drupal\Core\Ajax\AppendCommand; use Drupal\Core\Controller\ControllerBase; -use Drupal\examples\Utility\DescriptionTemplateTrait; -use Symfony\Component\HttpFoundation\JsonResponse; +use Drupal\Core\Database\Connection; use Drupal\Core\Link; use Drupal\Core\Url; -use Drupal\Core\Ajax\AppendCommand; -use Drupal\Core\Database\Database; -use Drupal\Core\Database\Connection; -use Drupal\Component\Utility\SafeMarkup; +use Drupal\examples\Utility\DescriptionTemplateTrait; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; /** * Controller routines for AJAX example routes. */ class AjaxExampleController extends ControllerBase { + use DescriptionTemplateTrait; - protected $connection; /** - * {@inheritdoc} + * The database connection. + * + * @var \Drupal\Core\Database\Connection */ - protected function getModuleName() { - return 'ajax_example'; + protected $connection; + + public static function create(ContainerInterface $container) { + return new static( + $container->get('database') + ); + } + + public function __construct(Connection $connection) { + $this->connection = $connection; } /** - * + * {@inheritdoc} */ - public function basicInstructions() { - return [ - $this->description(), - ]; + protected function getModuleName() { + return 'ajax_example'; } /** @@ -41,21 +51,22 @@ class AjaxExampleController extends ControllerBase { * This is the menu handler for * examples/ajax_example/progressbar/progress/$time. * - * This function is our wholly arbitrary job that we're checking the status for. - * In this case, we're reading a system variable that is being updated by + * This function is our wholly arbitrary job that we're checking the status + * for. In this case, we're reading a system variable that is being updated by * ajax_example_progressbar_callback(). * * We set up the AJAX progress bar to check the status every second, so this * will execute about once every second. * * The progress bar JavaScript accepts two values: message and percentage. We - * set those in an array and in the end convert it JSON for sending back to the - * client-side JavaScript. + * set those in an array and in the end convert it JSON for sending back to + * the client-side JavaScript. * * @param int $time * Timestamp. * * @return \Symfony\Component\HttpFoundation\JsonResponse + * JSON response to the AJAX request. */ public function progressbarProgress($time) { $progress = [ @@ -142,31 +153,32 @@ URL whether JS was enabled or not, letting it do different things based on that. * the URL and thus we are doing an AJAX and can return an array of commands. * * @param string $type - * Either 'ajax' or 'nojs. Type is simply the normal URL argument to this URL. + * Either 'ajax' or 'nojs. Type is simply the normal URL argument to this + * URL. * * @return string|array * If $type == 'ajax', returns an array of AJAX Commands. * Otherwise, just returns the content, which will end up being a page. */ - public function ajaxlinkresponse($type = 'ajax') { + public function ajaxLinkResponse($type = 'ajax') { if ($type == 'ajax') { $output = $this->t("This is some content delivered via AJAX"); $response = new AjaxResponse(); $response->addCommand(new AppendCommand('#myDiv', $output)); - // See ajax_example_advanced.inc for more details on the available commands - // and how to use them. + // See ajax_example_advanced.inc for more details on the available + // commands and how to use them. // $page = array('#type' => 'ajax', '#commands' => $commands); // ajax_deliver($response); return $response; } - else { - $output = $this->t("This is some content delivered via a page load."); - return $output; - } + $response = new Response($this->t("This is some content delivered via a page load.")); + return $response; } /** + * User autocomplete callback. + * * It works simply by searching usernames (and of course in Drupal usernames * are unique, so can be used for identifying a record.) * @@ -174,20 +186,25 @@ URL whether JS was enabled or not, letting it do different things based on that. * * key: string which will be displayed once the autocomplete is selected * * value: the value which will is displayed in the autocomplete pulldown. * - * In the simplest cases (see drupal/ajax_example/form/AjaxExampleAutocomplete.php) + * In the simplest cases (see + * drupal/ajax_example/form/AjaxExampleAutocomplete.php) * these are the same, andnothing needs to be done. However, more complicated * autocompletes require more work. Here we demonstrate the difference by * displaying the UID along with the username in the dropdown. * * In the end, though, we'll be doing something with the value that ends up in - * the textfield, so it needs to uniquely identify the record we want to access. - * This is demonstrated in ajax_example_unique_autocomplete(). + * the textfield, so it needs to uniquely identify the record we want to + * access. This is demonstrated in ajax_example_unique_autocomplete(). * + * @param \Drupal\Core\Database\Connection $connection + * The database connection. * @param string $string * The string that will be searched. + * + * @return Symfony\Component\HttpFoundation\JsonResponse + * The JSON response to the AJAX request. */ - public function ajax_example_simple_user_autocomplete_callback(Connection $connection, $string = "") { - $this->connection = Connection::$connection; + public function simpleUserAutocompleteCallback(Connection $connection, $string = "") { $matches = []; if ($string) { @@ -198,9 +215,9 @@ URL whether JS was enabled or not, letting it do different things based on that. ->range(0, 10) ->execute(); foreach ($result as $user) { - // In the simplest case (see user_autocomplete), the key and the value are - // the same. Here we'll display the uid along with the username in the - // dropdown. + // In the simplest case (see user_autocomplete), the key and the value + // are the same. Here we'll display the uid along with the username in + // the dropdown. $matches[] = ['value' => $user->name, 'label' => $user->uid]; $matches[$user->name] = SafeMarkup::check_plain($user->name) . " (uid=$user->uid)"; } @@ -227,8 +244,7 @@ URL whether JS was enabled or not, letting it do different things based on that. * @param string $string * The string that will be searched. */ - public function ajax_example_unique_node_autocomplete_callback($string = "") { - $this->connection = Connection::$connection; + public function uniqueNodeAutocompleteCallback($string = "") { $matches = []; if ($string) { @@ -245,26 +261,29 @@ URL whether JS was enabled or not, letting it do different things based on that. return new JsonResponse($matches); } - /** - * + /* + * @todo: is this even in use? */ - public function ajax_example_node_by_author_node_autocomplete_callback($author_uid, $string = "") { - $this->connection = Connection::$connection; - $matches = []; - if ($author_uid > 0 && trim($string)) { - $db = Database::getConnection(); - $result = $db->select('node') - ->fields('node', ['nid', 'title']) - ->condition('uid', $author_uid) - ->condition('title', $db->escapeLike($string) . '%', 'LIKE') - ->range(0, 10) - ->execute(); - foreach ($result as $node) { - $matches[$node->title . " [$node->nid]"] = SafeMarkup::check_plain($node->title); - } - } + /* public function ajax_example_node_by_author_node_autocomplete_callback( + * $author_uid, $string = "") { + $this->connection = Connection::$connection; + $matches = []; + if ($author_uid > 0 && trim($string)) { + $db = Database::getConnection(); + $result = $db->select('node') + ->fields('node', ['nid', 'title']) + ->condition('uid', $author_uid) + ->condition('title', $db->escapeLike($string) . '%', 'LIKE') + ->range(0, 10) + ->execute(); + foreach ($result as $node) { + $matches[$node->title . " [$node->nid]"] = + SafeMarkup::check_plain($node->title); + } + } - return new JsonResponse($matches); + return new JsonResponse($matches); } + */ } diff --git a/ajax_example/src/Form/AjaxExampleAddMore.php b/ajax_example/src/Form/AjaxExampleAddMore.php index 8c3cf0e..c43dc09 100644 --- a/ajax_example/src/Form/AjaxExampleAddMore.php +++ b/ajax_example/src/Form/AjaxExampleAddMore.php @@ -8,22 +8,23 @@ use Drupal\Core\Url; use Drupal\Core\Link; /** - * + * AJAX example add more. */ class AjaxExampleAddMore extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_addmore'; } /** - * This example shows a button to "add more" - add another textfield, and - * the corresponding "remove" button. + * Build the example form. */ public function buildForm(array $form, FormStateInterface $form_state, $no_js_use = FALSE) { + // This example shows a button to "add more" - add another textfield, and + // the corresponding "remove" button. $url = Url::fromUri('internal:/examples/ajax-example/add-more-nojs/'); $link = Link::fromTextAndUrl($this->t('non-js version'), $url)->toString(); @@ -38,7 +39,6 @@ class AjaxExampleAddMore extends FormBase { // Because we have many fields with the same values, we have to set // #tree to be able to access them. - $name_field = $form_state->get('num_names'); $form['#tree'] = TRUE; $form['names_fieldset'] = [ '#type' => 'fieldset', @@ -50,10 +50,13 @@ class AjaxExampleAddMore extends FormBase { // Build the fieldset with the proper number of names. We'll use // $form_state['num_names'] to determine the number of textfields to build. - if (empty($name_field)) { - $name_field = $form_state->set('num_names', 1); + $name_fields = $form_state->get('num_names'); + if (empty($name_fields)) { + $name_fields = 1; + $form_state->set('num_names', $name_fields); } - for ($i = 0; $i < $name_field; $i++) { + $form['num_names'] = $name_fields; + for ($i = 0; $i < $name_fields; $i++) { $form['names_fieldset']['name'][$i] = [ '#type' => 'textfield', '#title' => t('Name'), diff --git a/ajax_example/src/Form/AjaxExampleAdvancedCommands.php b/ajax_example/src/Form/AjaxExampleAdvancedCommands.php index 795c46d..a4d1af8 100644 --- a/ajax_example/src/Form/AjaxExampleAdvancedCommands.php +++ b/ajax_example/src/Form/AjaxExampleAdvancedCommands.php @@ -35,7 +35,7 @@ class AjaxExampleAdvancedCommands extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_Advanced'; } @@ -220,10 +220,14 @@ class AjaxExampleAdvancedCommands extends FormBase { '#title' => $this->t("Demonstrates the Ajax 'restripe' command."), ]; + $options = range (-1, 10); + $options = array_shift($options); $form['restripe_command_example_fieldset']['restripe_num_rows'] = [ '#type' => 'select', - '#default_value' => !empty($form_state->getValue('restripe_num_rows')) ? $form_state->getValue('restripe_num_rows') : 1, - '#options' => [1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 10 => 10], + '#default_value' => + !empty($form_state->getValue('restripe_num_rows')) ? + $form_state->getValue('restripe_num_rows') : 1, + '#options' => $options, '#ajax' => [ 'callback' => '::ajax_example_advanced_commands_restripe_num_rows', 'method' => 'replace', diff --git a/ajax_example/src/Form/AjaxExampleAutocheckboxes.php b/ajax_example/src/Form/AjaxExampleAutocheckboxes.php index 4e72b32..3006624 100644 --- a/ajax_example/src/Form/AjaxExampleAutocheckboxes.php +++ b/ajax_example/src/Form/AjaxExampleAutocheckboxes.php @@ -13,7 +13,7 @@ class AjaxExampleAutocheckboxes extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_autocheckbox'; } diff --git a/ajax_example/src/Form/AjaxExampleAutocomplete.php b/ajax_example/src/Form/AjaxExampleAutocomplete.php index 98aa41d..37e3d35 100644 --- a/ajax_example/src/Form/AjaxExampleAutocomplete.php +++ b/ajax_example/src/Form/AjaxExampleAutocomplete.php @@ -13,7 +13,7 @@ class AjaxExampleAutocomplete extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_autocomplete'; } diff --git a/ajax_example/src/Form/AjaxExampleAutocompleteAuthor.php b/ajax_example/src/Form/AjaxExampleAutocompleteAuthor.php index 0ea5d62..bd1bf2e 100644 --- a/ajax_example/src/Form/AjaxExampleAutocompleteAuthor.php +++ b/ajax_example/src/Form/AjaxExampleAutocompleteAuthor.php @@ -17,7 +17,7 @@ class AjaxExampleAutocompleteAuthor extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_autocompleteauthor'; } @@ -43,8 +43,8 @@ class AjaxExampleAutocompleteAuthor extends FormBase { ], ]; - // This form element with autocomplete will be replaced by #ajax whenever the - // author changes, allowing the search to be limited by user. + // This form element with autocomplete will be replaced by #ajax whenever + // the author changes, allowing the search to be limited by user. $form['node'] = [ '#type' => 'textfield', '#title' => t('Choose a node by title'), @@ -95,8 +95,8 @@ class AjaxExampleAutocompleteAuthor extends FormBase { // extracts the numeric portion. $result = preg_match('/\[([0-9]+)\]$/', $title, $matches); if ($result > 0) { - // If $result is nonzero, we found a match and can use it as the index into - // $matches. + // If $result is nonzero, we found a match and can use it as the index + // into $matches. $nid = $matches[$result]; // Verify that it's a valid nid. $node = Node::load($nid); @@ -104,11 +104,11 @@ class AjaxExampleAutocompleteAuthor extends FormBase { $form_state->setErrorByName($form['node'], t('Sorry, no node with nid %nid can be found', ['%nid' => $nid])); return; } - // BUT: Not everybody will have javascript turned on, or they might hit ESC - // and not use the autocomplete values offered. In that case, we can attempt - // to come up with a useful value. This is not absolutely necessary, and we - // *could* just emit a form_error() as below. Here we'll find the *first* - // matching title and assume that is adequate. + // BUT: Not everybody will have javascript turned on, or they might hit + // ESC and not use the autocomplete values offered. In that case, we can + // attempt to come up with a useful value. This is not absolutely + // necessary, and we *could* just emit a form_error() as below. Here we'll + // find the *first* matching title and assume that is adequate. else { $db = Database::getConnection(); $nid = $db->select('node') @@ -120,8 +120,8 @@ class AjaxExampleAutocompleteAuthor extends FormBase { ->fetchField(); } - // Now, if we somehow found a nid, assign it to the node. If we failed, emit - // an error. + // Now, if we somehow found a nid, assign it to the node. If we failed, + // emit an error. if (!empty($nid)) { $form_state->setValue('node', $nid); } diff --git a/ajax_example/src/Form/AjaxExampleAutotextfields.php b/ajax_example/src/Form/AjaxExampleAutotextfields.php index 4150f3f..d83a1e7 100644 --- a/ajax_example/src/Form/AjaxExampleAutotextfields.php +++ b/ajax_example/src/Form/AjaxExampleAutotextfields.php @@ -13,7 +13,7 @@ class AjaxExampleAutotextfields extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_autotextfields'; } @@ -80,8 +80,8 @@ class AjaxExampleAutotextfields extends FormBase { /** * Callback for autotextfields. * - * Selects the piece of the form we want to use as replacement text and returns - * it as a form (renderable array). + * Selects the piece of the form we want to use as replacement text and + * returns it as a form (renderable array). */ public function prompt($form, FormStateInterface $form_state) { return $form['textfields']; diff --git a/ajax_example/src/Form/AjaxExampleDependentDropdown.php b/ajax_example/src/Form/AjaxExampleDependentDropdown.php index cb1d6ee..c2c9260 100644 --- a/ajax_example/src/Form/AjaxExampleDependentDropdown.php +++ b/ajax_example/src/Form/AjaxExampleDependentDropdown.php @@ -13,7 +13,7 @@ class AjaxExampleDependentDropdown extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_dependentdropdown'; } @@ -28,8 +28,8 @@ class AjaxExampleDependentDropdown extends FormBase { */ public function buildForm(array $form, FormStateInterface $form_state) { $options_first = _ajax_example_get_first_dropdown_options(); - // If we have a value for the first dropdown from $form_state['values'] we use - // this both as the default value for the first dropdown and also as a + // If we have a value for the first dropdown from $form_state['values'] we + // use this both as the default value for the first dropdown and also as a // parameter to pass to the function that retrieves the options for the // second dropdown. $selected = !empty($form_state->getValue('dropdown_first')) ? $form_state->getValue('dropdown_first') : key($options_first); diff --git a/ajax_example/src/Form/AjaxExampleDependentDropdownDegardes.php b/ajax_example/src/Form/AjaxExampleDependentDropdownDegrades.php similarity index 95% rename from ajax_example/src/Form/AjaxExampleDependentDropdownDegardes.php rename to ajax_example/src/Form/AjaxExampleDependentDropdownDegrades.php index 1a32b42..719354e 100644 --- a/ajax_example/src/Form/AjaxExampleDependentDropdownDegardes.php +++ b/ajax_example/src/Form/AjaxExampleDependentDropdownDegrades.php @@ -25,13 +25,13 @@ use Drupal\Core\Form\FormStateInterface; * ways to call this form, one normal ($no_js_use = FALSE) and one simulating * Javascript disabled ($no_js_use = TRUE). */ -class AjaxExampleDependentDropdownDegardes extends FormBase { +class AjaxExampleDependentDropdownDegrades extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { - return 'ajax_example_dependentdropdowndegardes'; + public function getFormId() { + return 'ajax_example_dependentdropdowndegrades'; } /** @@ -40,8 +40,8 @@ class AjaxExampleDependentDropdownDegardes extends FormBase { public function buildForm(array $form, FormStateInterface $form_state, $no_js_use = FALSE) { $options_first = _ajax_example_get_first_dropdown_options(); - // If we have a value for the first dropdown from $form_state['values'] we use - // this both as the default value for the first dropdown and also as a + // If we have a value for the first dropdown from $form_state['values'] we + // use this both as the default value for the first dropdown and also as a // parameter to pass to the function that retrieves the options for the // second dropdown. $selected = !empty($form_state->getValue('dropdown_first')) ? $form_state->getValue('dropdown_first') : key($options_first); @@ -109,7 +109,8 @@ class AjaxExampleDependentDropdownDegardes extends FormBase { '#attributes' => ['class' => ['enabled-for-ajax']], ]; - // Disable dropdown_second if a selection has not been made on dropdown_first. + // Disable dropdown_second if a selection has not been made on dropdown + // first. if (empty($form_state->getValue('dropdown_first'))) { $form['dropdown_second_fieldset']['dropdown_second']['#disabled'] = TRUE; $form['dropdown_second_fieldset']['submit']['#disabled'] = FALSE; diff --git a/ajax_example/src/Form/AjaxExampleDynamicSectionsDegardes.php b/ajax_example/src/Form/AjaxExampleDynamicSectionsDegrades.php similarity index 98% rename from ajax_example/src/Form/AjaxExampleDynamicSectionsDegardes.php rename to ajax_example/src/Form/AjaxExampleDynamicSectionsDegrades.php index 8e55141..607a174 100644 --- a/ajax_example/src/Form/AjaxExampleDynamicSectionsDegardes.php +++ b/ajax_example/src/Form/AjaxExampleDynamicSectionsDegrades.php @@ -20,13 +20,13 @@ use Drupal\Core\Url; * The third $no_js_use argument is strictly for demonstrating operation * without javascript, without making the user/developer turn off javascript. */ -class AjaxExampleDynamicSectionsDegardes extends FormBase { +class AjaxExampleDynamicSectionsDegrades extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { - return 'ajax_example_dynamicsectiondegardes'; + public function getFormId() { + return 'ajax_example_dynamicsectiondegrades'; } /** diff --git a/ajax_example/src/Form/AjaxExampleNodeFormAlter.php b/ajax_example/src/Form/AjaxExampleNodeFormAlter.php index bf1a77d..1d8e25d 100644 --- a/ajax_example/src/Form/AjaxExampleNodeFormAlter.php +++ b/ajax_example/src/Form/AjaxExampleNodeFormAlter.php @@ -7,15 +7,12 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Database\Connection; /** - * + * AJAX example for node form alter. */ class AjaxExampleNodeFormAlter extends FormBase { protected $connection; - /** - * - */ public function __construct(Connection $connection) { $this->connection = $connection; } @@ -23,7 +20,7 @@ class AjaxExampleNodeFormAlter extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_modeformalter'; } diff --git a/ajax_example/src/Form/AjaxExampleProgressBar.php b/ajax_example/src/Form/AjaxExampleProgressBar.php index 0ca8653..8bdd599 100644 --- a/ajax_example/src/Form/AjaxExampleProgressBar.php +++ b/ajax_example/src/Form/AjaxExampleProgressBar.php @@ -15,7 +15,7 @@ class AjaxExampleProgressBar extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_progressbar'; } @@ -34,9 +34,9 @@ class AjaxExampleProgressBar extends FormBase { '#type' => 'submit', '#value' => $this->t('Submit'), '#ajax' => [ - // Here we set up our AJAX callback handler. + // Here we set up our AJAX callback handler. 'callback' => '::prompt', - // Tell FormAPI about our progress bar. + // Tell FormAPI about our progress bar. 'progress' => [ 'type' => 'bar', 'message' => $this->t('Execute..'), @@ -60,8 +60,8 @@ class AjaxExampleProgressBar extends FormBase { * completed. * * While this is occurring, ajax_example_progressbar_progress() will be called - * a number of times by the client-sid JavaScript, which will poll the variable - * being set here. + * a number of times by the client-sid JavaScript, which will poll the + * variable being set here. * * @see \Drupal\ajax_example\Controller\AjaxExampleController::progressbarProgress */ diff --git a/ajax_example/src/Form/AjaxExampleSimplest.php b/ajax_example/src/Form/AjaxExampleSimplest.php index 0b2aa3c..b910fba 100644 --- a/ajax_example/src/Form/AjaxExampleSimplest.php +++ b/ajax_example/src/Form/AjaxExampleSimplest.php @@ -13,7 +13,7 @@ class AjaxExampleSimplest extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_simplest'; } @@ -31,7 +31,8 @@ class AjaxExampleSimplest extends FormBase { ], '#ajax' => [ // #ajax has two required keys: callback and wrapper. - // 'callback' is a function that will be called when this element changes. + // 'callback' is a function that will be called when this element + // changes. 'callback' => '::prompt', // 'wrapper' is the HTML id of the page element that will be replaced. 'wrapper' => 'replace_textfield_div', @@ -41,7 +42,8 @@ class AjaxExampleSimplest extends FormBase { ], ]; - // This entire form element will be replaced whenever 'changethis' is updated. + // This entire form element will be replaced whenever 'changethis' is + // updated. $form['replace_textfield'] = [ '#type' => 'textfield', '#title' => $this->t("Why"), diff --git a/ajax_example/src/Form/AjaxExampleSubmitDriven.php b/ajax_example/src/Form/AjaxExampleSubmitDriven.php index 703d87c..f5297d5 100644 --- a/ajax_example/src/Form/AjaxExampleSubmitDriven.php +++ b/ajax_example/src/Form/AjaxExampleSubmitDriven.php @@ -13,7 +13,7 @@ class AjaxExampleSubmitDriven extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_autotextfields'; } @@ -56,9 +56,9 @@ class AjaxExampleSubmitDriven extends FormBase { * Renderable array (the box element) */ public function prompt(array &$form, FormStateInterface $form_state) { - // In most cases, it is recommended that you put this logic in form generation - // rather than the callback. Submit driven forms are an exception, because - // you may not want to return the form at all. + // In most cases, it is recommended that you put this logic in form + // generation rather than the callback. Submit driven forms are an + // exception, because you may not want to return the form at all. $element = $form['box']; $element['#markup'] = "Clicked submit ({$form_state->getValue('op')}): " . date('c'); return $element; diff --git a/ajax_example/src/Form/AjaxExampleUniquecomplete.php b/ajax_example/src/Form/AjaxExampleUniqueComplete.php similarity index 96% rename from ajax_example/src/Form/AjaxExampleUniquecomplete.php rename to ajax_example/src/Form/AjaxExampleUniqueComplete.php index 7f18260..4ca6b8f 100644 --- a/ajax_example/src/Form/AjaxExampleUniquecomplete.php +++ b/ajax_example/src/Form/AjaxExampleUniqueComplete.php @@ -15,12 +15,12 @@ use Drupal\node\Entity\Node; * but must keep track of the nid, because titles are certainly not guaranteed * to be unique. */ -class AjaxExampleUniquecomplete extends FormBase { +class AjaxExampleUniqueComplete extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_uniquecomplete'; } @@ -62,8 +62,8 @@ class AjaxExampleUniquecomplete extends FormBase { // extracts the numeric portion. $result = preg_match('/\[([0-9]+)\]$/', $title, $matches); if ($result > 0) { - // If $result is nonzero, we found a match and can use it as the index into - // $matches. + // If $result is nonzero, we found a match and can use it as the index + // into $matches. $nid = $matches[$result]; // Verify that it's a valid nid. $node = Node::load($nid); diff --git a/ajax_example/src/Form/AjaxExampleWizard.php b/ajax_example/src/Form/AjaxExampleWizard.php index adffbd5..c61d2e9 100644 --- a/ajax_example/src/Form/AjaxExampleWizard.php +++ b/ajax_example/src/Form/AjaxExampleWizard.php @@ -10,14 +10,14 @@ use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\HtmlCommand; /** - * + * AJAX example wizard. */ class AjaxExampleWizard extends FormBase { /** * {@inheritdoc} */ - public function getFormID() { + public function getFormId() { return 'ajax_example_wizard'; } @@ -35,7 +35,7 @@ class AjaxExampleWizard extends FormBase { ->toString(); // $form['#prefix'] = '
'; - // $form['#suffix'] = '
'; + // $form['#suffix'] = ''; // We want to deal with hierarchical form values. $form['#tree'] = TRUE; $form['description'] = [ @@ -125,7 +125,8 @@ class AjaxExampleWizard extends FormBase { } else { $step = $form_state->getValue('step'); - // Increment or decrement the step as needed. Recover values if they exist. + // Increment or decrement the step as needed. Recover values if they + // exist. if ($form_state->getTriggeringElement()['#value']->__toString() == $this->t('Next step')) { $step++; } diff --git a/ajax_example/templates/description.html.twig b/ajax_example/templates/description.html.twig index e668459..37e4d42 100644 --- a/ajax_example/templates/description.html.twig +++ b/ajax_example/templates/description.html.twig @@ -9,8 +9,8 @@ Description text for the Ajax Example. {% set ajax_generate_textfields = path('ajax_example.autotextfields') %} {% set ajax_submit = path('ajax_example.submit-driven-ajax') %} {% set ajax_dependent_dropdown = path('ajax_example.dependent_dropdown') %} -{% set ajax_dependent_dropdown_degrade = path('ajax_example.dependent_dropdown_degardes') %} -{% set ajax_dependent_dropdown_nojs = path('ajax_example.dependent_dropdown_degardes_nojava') %} +{% set ajax_dependent_dropdown_degrade = path('ajax_example.dependent_dropdown_degrades') %} +{% set ajax_dependent_dropdown_nojs = path('ajax_example.dependent_dropdown_degrades_nojava') %} {% set ajax_dynamic_dropdown = path('ajax_example.dynamic_sections') %} {% set ajax_dynamic_dropdown_nojs = path('ajax_example.dynamic_sections_nojava') %} {% set ajax_wizard_example = path('ajax_example.wizard') %} @@ -27,8 +27,8 @@ Description text for the Ajax Example.

Generate textfields

Submit-driven AJAX

Dependent dropdown

-

Dependent dropdown degarde

-

Dependent dropdown degardes w/JS turned off

+

Dependent dropdown degrade

+

Dependent dropdown degrades w/JS turned off

Dynamic Sections (with graceful degradation)

Dynamic Sections (with graceful degradation) w/js turned off

AJAX Wizard Example

diff --git a/ajax_example/tests/src/Functional/AjaxExampleMenuTest.php b/ajax_example/tests/src/Functional/AjaxExampleMenuTest.php new file mode 100644 index 0000000..09cecd9 --- /dev/null +++ b/ajax_example/tests/src/Functional/AjaxExampleMenuTest.php @@ -0,0 +1,83 @@ +drupalLogin( + $this->createUser(['access content', 'access user profiles']) + ); + + $assertion = $this->assertSession(); + + // Click all the submit and cancel buttons. + $routes = [ + 'ajax_example.description' => [], + 'ajax_example.simplest' => [], + // @todo progress bar example is broken. + // 'ajax_example.progresssbar' => ['Submit'], + // @todo not found + // 'ajax_example.progresssbarProgress' => '', + // @todo not found. + // 'ajax_example.autocheckboxes' => '', + 'ajax_example.autotextfields' => ['Click Me'], + 'ajax_example.submit-driven-ajax' => ['Submit'], + 'ajax_example.dependent_dropdown' => ['Submit'], + 'ajax_example.dependent_dropdown_degrades' => ['Choose', 'OK'], + 'ajax_example.dependent_dropdown_degrades_nojava' => ['Choose', 'OK'], + 'ajax_example.dynamic_sections' => ['Choose', 'OK'], + 'ajax_example.dynamic_sections_nojava' => ['Choose'], + 'ajax_example.wizard' => ['Next step'], + 'ajax_example.wizardnojs' => ['Next step'], + // @todo add-more has trouble with num_names. + // 'ajax_example.addmore' => ['Submit'], + // 'ajax_example.addmorenojs' => ['Submit'], + // @todo advanced-commands does not render. + // 'ajax_example.advanced' => ['Submit'], + // @todo ajax-link is broken. + // 'ajax_example.Ajaxlink' => [], + 'ajax_example.Ajaxlinkrender' => [], + 'ajax_example.Ajaxlinkcall' => [], + // @todo simple autocomplete is 403. + // 'ajax_example.AutocompleteSimplest' => [], + // 'ajax_example.AutocompleteSimplestcallback' => [], + 'ajax_example.Autocompletenode' => [], + 'ajax_example.Autocompletenodecallback' => [], + ]; + + foreach ($routes as $route => $buttons) { + $path = Url::fromRoute($route); + $this->drupalGet($path); + $assertion->statusCodeEquals(200); + foreach ($buttons as $button) { + $this->drupalPostForm($path, [], $button); + $assertion->statusCodeEquals(200); + } + } + } + +} diff --git a/examples.module b/examples.module index ace2f86..1f7cd9a 100644 --- a/examples.module +++ b/examples.module @@ -35,6 +35,7 @@ function examples_toolbar() { // First, build an array of all example modules and their routes. // We resort to this hard-coded way so as not to muck up each example. $examples = [ + 'ajax_example' => 'ajax_example.description', 'batch_example' => 'batch_example.form', 'block_example' => 'block_example.description', 'cache_example' => 'cache_example.description', @@ -45,7 +46,6 @@ function examples_toolbar() { 'email_example' => 'email_example.description', 'events_example' => 'events_example.description', 'fapi_example' => 'fapi_example.description', - 'ajax_example' => 'ajax_example.description', 'field_example' => 'field_example.description', 'field_permission_example' => 'field_permission_example.description', 'file_example' => 'file_example.fileapi',