Điểm:3

Biểu mẫu AJAX bằng cách sử dụng một lớp con của ContentEntityForm kích hoạt/gọi/gọi WidgetBase::massageFormValues() hai lần

lá cờ cn

Tôi đang sử dụng biểu mẫu AJAX. Biểu mẫu này tôi xây dựng từ một lớp con của Nội dungThực thểHình thức. Thực thể được chỉnh sửa bởi biểu mẫu này có một trường Cánh đồng của tôi. Để đưa tất cả các giá trị trường vào một cấu trúc phù hợp mà tôi đang sử dụng massageFormValues() Trong MyFieldWidget lớp (phân lớp của Tiện ích cơ sở).

Vấn đề nhỏ là: phương pháp massageFormValues() được gọi hai lần trên mỗi lần gửi. Không có vấn đề nào khác với biểu mẫu. Tôi có thể chỉnh sửa chính xác các giá trị trên biểu mẫu này.

Vì vậy, đây chỉ là câu hỏi về sự hiểu biết: tại sao Drupal lại gọi massageFormValues() hai lần trên mỗi lần gửi.

Mã được đề cập và mã (rất đơn giản) của tôi:

Bộ điều khiển ajax của tôi

lớp AjaxController mở rộng ControllerBase {
  ...
  ...

  hàm công khai myController($eid) {

    $myEntity = $this->entityTypeManager()->getStorage('my_entity')->load($eid);
    $form = $this->entityFormBuilder()->getForm($myEntity, 'my_mode');
    $renderer = \Drupal::service('renderer');
    $output = $renderer->renderRoot($form);
  
    $response = new AjaxResponse();
    $response->addCommand(OpenModalDialogCommand mới($title, $output));
 
    trả lại phản hồi $;
  }
  ...
  ...
}

Hình thức của tôi là một lớp con của ContentEntityForm và nó là một hình thức chế độ cho cách thức my_mode của thực thể my_entity:

lớp MyForm mở rộng ContentEntityForm {

 ...
 ...
  hành động chức năng được bảo vệ (mảng $form, FormStateInterface $form_state) {
    $actions = parent::actions($form, $form_state);

    $actions['submit'] = [
      '#type' => 'gửi',
      '#value' => t('Lưu'),
      '#ajax' => [
        'gọi lại' => '::ajaxCallback',
        'sự kiện' => 'mousedown',
      ],
    ];

  trả lại hành động $;
  }
  ...
  ...
}

Lớp tiện ích trường của tôi:

class MyFieldWidget extends WidgetBase thực hiện ContainerFactoryPluginInterface {
...
...

  chức năng công khai massageFormValues(mảng $values, mảng $form, FormStateInterface $form_state) { 

    // MÃ NÀY ĐƯỢC GỌI HAI LẦN TRÊN MỖI LẦN GỬI CỦA NÚT GỬI CỦA TÔI ĐƯỢC ĐỊNH NGHĨA Ở TRÊN
    // NHƯNG TẠI SAO LẠI HAI LẦN?

    trả về $rightStructureValues;
  }

...
...
}
Điểm:4
lá cờ cn

Trong một yêu cầu Ajax, biểu mẫu được xây dựng lại từ đầu. Điều này thường được hỏi ở đây tại sao phương thức xây dựng biểu mẫu được gọi hai hoặc thậm chí ba lần. Có vẻ như thực thể cũng được xây dựng lại khi biểu mẫu được gửi qua Ajax:

Drupal\Core\Entity\EntityForm::afterBuild

  /**
   * Gọi lại phần tử biểu mẫu #after_build: Cập nhật thực thể với dữ liệu đã gửi.
   *
   * Cập nhật đối tượng thực thể $this->nội bộ với các giá trị đã gửi khi
   * biểu mẫu đang được xây dựng lại (ví dụ: gửi qua AJAX), để tiếp theo
   * xử lý (ví dụ: gọi lại AJAX) có thể dựa vào nó.
   */
  hàm công khai afterBuild(mảng $element, FormStateInterface $form_state) {
    // Xây dựng lại thực thể nếu #after_build đang được gọi như một phần của biểu mẫu
    // xây dựng lại, tức là nếu chúng tôi đang xử lý đầu vào.
    nếu ($form_state->isProcessingInput()) {
      $this->entity = $this->buildEntity($element, $form_state);
    }

    trả lại phần tử $;
  }

Điều này sẽ kích hoạt phương thức được đề cập trong các tiện ích trường.

Hermann Schwarz avatar
lá cờ cn
Thật không may, tôi không thể ngăn việc gọi massageFormValues() hai lần thay mặt cho afterBuild(). Nhưng nếu bạn có thể mô tả chi tiết, cách thức hoạt động của nó, nó sẽ rất tuyệt. Tôi sẽ cung cấp giải pháp của riêng tôi như một câu trả lời.
4uk4 avatar
lá cờ cn
Không có gì sai với phương pháp này và toàn bộ quá trình xây dựng biểu mẫu đang được gọi hai lần. Những người bảo trì cốt lõi đã quyết định xây dựng lại biểu mẫu (và thực thể trong trường hợp này) hơn là lấp đầy cơ sở dữ liệu bằng các biểu mẫu Ajax được lưu trong bộ nhớ cache không bao giờ được gửi.
Hermann Schwarz avatar
lá cờ cn
Tôi hiểu. Cảm ơn bạn, 4k4. Tôi nhận ra, đó là tối ưu hóa vi mô tôi thực hiện :-).
Điểm:1
lá cờ cn

Cách giải quyết/giải pháp của tôi. massageFormValues() vẫn được Drupal gọi hai lần, nhưng logic của tôi trong đó sẽ chỉ được thực thi một lần, sau khi quá trình xác thực biểu mẫu hoàn tất:

MyFieldWidgetClass.php:

class MyFieldWidget extends WidgetBase thực hiện ContainerFactoryPluginInterface {
...
...

  chức năng công khai massageFormValues(mảng $values, mảng $form, FormStateInterface $form_state) { 

    // massageFormValues() được gọi hai lần: trên validateForm và trên submitForm
    // chúng ta chỉ cần massageFormValues ​​một lần, sau khi $form_state->isValidationComplete() là TRUE
    if(!$form_state->isValidationComplete()) {
      trở lại [];
    }
    ...
    ...
    trả về $rightStructureValues;
  }

...
...
}

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.