DRUPAL模块开发 - DRUPAL8 AJAX Forms

翻译者:长风Drupal开发:Drupal8 AJAX Forms

原文链接:https://www.drupal.org/docs/8/api/menu-api/providing-module-defined-contextual-links

Drupal开发中,添加ajax到表单中可以允许Drupal开发者动态的更新表单的表单字段和标记。
ajax的回调函数可以做以下事:
更新已经存在的字段或者添加新的标段字段。
执行各种预定义的ajax命令。(https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Ajax%21CommandInterface.php/interface/implements/CommandInterface/8.3.x)
粘贴ajax回调到一个字段
内容:
1、创建一个表单
2、ajax渲染元素
3、ajax的回调函数:渲染数组、html标签、ajax命令
4、在ajax的回调函数中自定义javascription
5、debugging ajax回调函数
6、更多的渲染

 

1、创建一个表单
 

$form['container']['output'] = [
  '#type' => 'textfield',
  '#size' => '60',
  '#disabled' => TRUE,
  '#value' => 'Hello, World!',
  '#attributes' => [
    'id' => ['edit-output'],
  ],
];


drupal将自动为所有的表单元素生成一个Id,你可以查看已经渲染的结果来找到Drupal已经生成的ID;尽管如此,无论什么原因,你修改这个ID将导致回调不能生效;
2、Ajax 渲染元素
在一个Drupal8表单元素中,渲染数组使用'ajax'标记,下面是一个Drupal8中使用Ajax的例子

$form['input'] = [
  '#type' => 'textfield',
  '#title' => 'A Textfield',
  '#description' => 'Enter a number to be validated via ajax.',
  '#size' => '60',
  '#maxlength' => '10',
  '#required' => TRUE,
  '#ajax' => [
    'callback' => 'sayHello',
    'event' => 'keyup',
    'wrapper' => 'edit-output',
    'progress' => [
      'type' => 'throbber',
      'message' => t('Verifying entry...'),
    ],
  ],
];


上面的Drupal8代码将创建一个Ajax 请求,当用户敲击键盘的时候这个请求将触发一个sayhello()的函数。
上面的ajax用到的属性如下 :
callback:通过ajax求情将触发的函数
event:触发请求的事件,蔽日click、keyup、change等
wrapper:这个元素的ID;也可以把这个ID包裹这元素的外面。
progress:当请求正在进行时用来为用户展示的信息,以便用户知道请求正在进行。

3、ajax回调函数
这里有不同的方法来相应Ajax请求。你既可以使用ajaxresponse对象并执行一个ajax命令,也可以使用html标签,来替换wrapper元素。
 

use Drupal\Core\Form\FormStateInterface;

public function sayHello(array &$form, FormStateInterface $form_state) : array {
  $elem = [
    '#type' => 'textfield',
    '#size' => '60',
    '#disabled' => TRUE,
    '#value' => 'Hello, ' . $form_state->getValue('input') . '!',
    '#attributes' => [
      'id' => ['edit-output'],
    ],
  ];

  return $elem;
}

4、在ajax回调中执行自断一的javascription
你可以写自定义的ajax命令。但是你只能于宁很少的Javascription,并且没有过多。AJAX InvokeCommand将被用来调用jquery的方法
你的ajax调用
 

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\InvokeCommand;


public function sayHello(array &$form, FormStateInterface $form_state) : AjaxResponse {
  $response = new AjaxResponse();
  $response->addCommand(new InvokeCommand(NULL, 'myAjaxCallback', ['My arguments']));
  return $response;
}
你的jquery方法

(function($)
{
  //argument passed from InvokeCommand
  $.fn.myAjaxCallback = function(argument)
  {
    console.log('myAjaxCallback is called.');
    //set some input field's value to 'My arguments'
    $('#some-wrapper input').attr('value', argument);
  };
})(jQuery);

5、Debugging AJAX 回调函数
kint可以用来在ajax回调中记录,非常简单的在你的回调函数中调用kint($form_state),来记录ajax错误或者WSOD,你可以使用ajaxresponse来显示kint()的结果,

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;


//implements HOOK_form_alter. add debug output container and ajax callback
function YOUR_MODULE_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if($form_id == 'your_form_id') {
    //add empty container to the form. it gets filled with
    //the kint output from our ajax event callback.
    $form['debug'] = [
      '#type' => 'container',
      '#attributes' => [
        'id' => ['debug-out'],
      ],
    ];
  }

  //here follows the code where you add the #ajax callback
  //to some field of this form. lets say a taxonomy reference select box
  $form['field_yourtaxonomy']['widget']['#ajax'] = array(
    'event' => 'change',
    'callback' => 'sayHello',
  );
}


//the callback function, triggered by changing selection of our taxonomy select box
public function sayHello(array &$form, FormStateInterface $form_state) : AjaxResponse  {
  $response = new AjaxResponse();
  $debugOut = @Kint::dump($form_state);
  $response->addCommand(new ReplaceCommand('#debug-out', $debugOut ));
  return $response;
}