Score:3

แบบฟอร์ม AJAX ที่ใช้คลาสย่อยของ ContentEntityForm เริ่มทำงาน/เรียกใช้/เรียก WidgetBase::massageFormValues() สองครั้ง

ธง cn

ฉันใช้แบบฟอร์ม AJAX แบบฟอร์มนี้ฉันสร้างจากคลาสย่อยของ ContentEntityForm. เอนทิตีที่แก้ไขโดยแบบฟอร์มนี้มีฟิลด์ มายฟิลด์. เพื่อนำค่าฟิลด์ทั้งหมดในโครงสร้างที่เหมาะสมที่ฉันใช้อยู่ ค่าแบบฟอร์มการนวด() ใน วิดเจ็ต MyField class (คลาสย่อยของ WidgetBase).

ปัญหาเล็กน้อยคือ: วิธีการ ค่าแบบฟอร์มการนวด() ถูกเรียกสองครั้งในการส่งทุกครั้ง ไม่มีปัญหาอื่น ๆ กับแบบฟอร์ม ฉันสามารถแก้ไขค่าในแบบฟอร์มนี้ได้อย่างถูกต้อง

ดังนั้นจึงเป็นเพียงคำถามของการทำความเข้าใจ: ทำไม Drupal ถึงโทรมา ค่าแบบฟอร์มการนวด() สองครั้งในการส่งทุกครั้ง

รหัสที่กล่าวถึงและของฉัน (ง่ายมาก):

ตัวควบคุม ajax ของฉัน

คลาส AjaxController ขยาย ControllerBase {
  ...
  ...

  ฟังก์ชั่นสาธารณะ myController ($ eid) {

    $myEntity = $this->entityTypeManager()->getStorage('my_entity')->load($eid);
    $form = $this->entityFormBuilder()->getForm($myEntity, 'my_mode');
    $renderer = \Drupal::service('เรนเดอร์');
    $output = $renderer->renderRoot($แบบฟอร์ม);
  
    $response = ใหม่ AjaxResponse();
    $response->addCommand(new OpenModalDialogCommand($title, $output));
 
    ส่งคืน $response;
  }
  ...
  ...
}

แบบฟอร์มของฉัน เป็นคลาสย่อยของ ContentEntityForm และเป็น แบบฟอร์มโหมด สำหรับ โหมด my_mode ของนิติบุคคล my_entity:

คลาส MyForm ขยาย ContentEntityForm {

 ...
 ...
  การกระทำของฟังก์ชันที่ได้รับการป้องกัน (อาร์เรย์ $form, FormStateInterface $form_state) {
    $actions = parent::actions($form, $form_state);

    $actions['ส่ง'] = [
      '#type' => 'ส่ง',
      '#value' => t('บันทึก'),
      '#อาแจ็กซ์' => [
        'callback' => '::ajaxCallback',
        'event' => 'mousedown',
      ]
    ];

  ส่งคืน $actions;
  }
  ...
  ...
}

คลาสวิดเจ็ตฟิลด์ของฉัน:

คลาส MyFieldWidget ขยาย WidgetBase ใช้ ContainerFactoryPluginInterface {
...
...

  ฟังก์ชันสาธารณะ massageFormValues ​​(อาร์เรย์ $values, อาร์เรย์ $form, FormStateInterface $form_state) { 

    // รหัสนี้ถูกเรียกใช้สองครั้งในทุก ๆ การส่งของปุ่มส่งของฉันที่กำหนดไว้ข้างต้น
    // แต่ทำไมสองครั้ง?

    คืน $rightStructureValues;
  }

...
...
}
Score:4
ธง cn

ในคำขอ Ajax แบบฟอร์มจะสร้างขึ้นใหม่ตั้งแต่เริ่มต้น คำถามนี้มักถูกถามที่นี่ว่าเหตุใดจึงเรียกวิธีการสร้างแบบฟอร์มสองหรือสามครั้ง ดูเหมือนว่าเอนทิตีจะถูกสร้างขึ้นใหม่เช่นกันเมื่อส่งแบบฟอร์มผ่าน Ajax:

Drupal\Core\Entity\EntityForm::afterBuild

  /**
   * องค์ประกอบฟอร์ม #after_build การเรียกกลับ: อัปเดตเอนทิตีด้วยข้อมูลที่ส่ง
   *
   * อัปเดตวัตถุ $this->entity ภายในด้วยค่าที่ส่งเมื่อ
   * ฟอร์มกำลังถูกสร้างขึ้นใหม่ (เช่น ส่งผ่าน AJAX) ดังนั้นในครั้งต่อไป
   * การประมวลผล (เช่น การโทรกลับ AJAX) สามารถพึ่งพาได้
   */
  ฟังก์ชั่นสาธารณะ afterBuild (องค์ประกอบ $ อาร์เรย์, FormStateInterface $ form_state) {
    // สร้างเอนทิตีใหม่หาก #after_build ถูกเรียกเป็นส่วนหนึ่งของฟอร์ม
    // สร้างใหม่ เช่น หากเรากำลังประมวลผลอินพุต
    ถ้า ($form_state->isProcessingInput()) {
      $this->entity = $this->buildEntity($องค์ประกอบ, $form_state);
    }

    ส่งคืนองค์ประกอบ $;
  }

วิธีนี้จะเรียกใช้เมธอดดังกล่าวในวิดเจ็ตฟิลด์

Hermann Schwarz avatar
cn flag
น่าเสียดายที่ฉันไม่สามารถป้องกันการเรียก massageFormValues() สองครั้งด้วยชื่อ afterBuild() แต่ถ้าจะให้อธิบายรายละเอียดวิธีการทำงานก็คงจะดี ฉันจะให้คำตอบของตัวเองเป็นคำตอบ
4uk4 avatar
cn flag
ไม่มีอะไรผิดปกติกับวิธีนี้และการสร้างแบบฟอร์มทั้งหมดจะถูกเรียกสองครั้ง ผู้ดูแลหลักตัดสินใจที่จะสร้างฟอร์มใหม่ (และเอนทิตีในกรณีนี้) มากกว่าที่จะเติมฐานข้อมูลด้วยฟอร์ม Ajax ที่แคชซึ่งไม่เคยถูกส่ง
Hermann Schwarz avatar
cn flag
ฉันเข้าใจ. ขอบคุณครับ 4k4 ฉันรู้ว่ามันเป็นการเพิ่มประสิทธิภาพระดับไมโครที่ฉันทำ :-)
Score:1
ธง cn

วิธีแก้ปัญหา/วิธีแก้ปัญหาของฉัน massageFormValues() ยังคงเรียกสองครั้งโดย Drupal แต่ตรรกะของฉันในนั้นจะถูกดำเนินการเพียงครั้งเดียว หลังจากการตรวจสอบแบบฟอร์มเสร็จสมบูรณ์:

MyFieldWidgetClass.php:

คลาส MyFieldWidget ขยาย WidgetBase ใช้ ContainerFactoryPluginInterface {
...
...

  ฟังก์ชันสาธารณะ massageFormValues ​​(อาร์เรย์ $values, อาร์เรย์ $form, FormStateInterface $form_state) { 

    // massageFormValues() ถูกเรียกสองครั้ง: บน validateForm และ บน submitForm
    // เราต้องการแค่ massageFormValues ​​หนึ่งครั้ง หลังจาก $form_state->isValidationComplete() เป็น TRUE
    ถ้า(!$form_state->isValidationComplete()) {
      กลับ [];
    }
    ...
    ...
    คืน $rightStructureValues;
  }

...
...
}

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา