Điểm:2

buildForm: cách phân biệt giữa tải lại trang và gọi lại ajax?

lá cờ br

Tôi đang tạo biểu mẫu tùy chỉnh trong Drupal 9, có một số lệnh gọi lại ajax.

trong thời gian xây dựngForm Tôi cần tải thêm một số dữ liệu thông qua lệnh gọi còn lại tới một dịch vụ bên ngoài, sau đó tôi đặt vào một private_tempstore Biến đổi.

Tôi muốn tránh gọi điểm cuối còn lại trong các cuộc gọi lại ajax và dựa vào biến được lưu trữ.

Tuy nhiên, tôi không thể tìm ra cách phân biệt giữa trường hợp "tải trang" và "trường hợp ajax". Có thể không?

tôi đã tìm thấy câu trả lời này mà dường như thường làm việc:

// Chỉ ví dụ cho ngắn gọn, thêm dịch vụ request_stack và gọi 
// getCurrentRequest() trên đó để lấy đối tượng yêu cầu nếu có thể.
$request = \Drupal::request();
$is_ajax = $request->isXmlHttpRequest();

Nhưng tôi muốn biết liệu có một số trợ giúp \ giải pháp nào sử dụng API biểu mẫu hay không.

lá cờ ru
IMHO không có logic biểu mẫu nào được dựa trên Tải trang so với Ajax. BigPipe của lõi đã cho có thể tải bất kỳ thứ gì bằng Ajax (hoặc không) tùy thuộc vào vị trí khối, môi trường, cấu hình, v.v..., đây có vẻ như là một con đường đảm bảo dẫn đến thất bại.
Giuseppe avatar
lá cờ br
@Hudri đó là một sự cân nhắc lớn mà tôi không nhận ra, cảm ơn bạn. Tuy nhiên, có cách nào khác để giải quyết câu hỏi này không? Ý tôi là, tôi muốn tránh thực hiện lệnh gọi phần còn lại bên ngoài cho mọi lệnh gọi lại ajax của biểu mẫu.
lá cờ ru
TBH Tôi không hiểu lắm lý do cho câu hỏi. `buildForm` có quyền truy cập vào `FormStateInterface $form_state`, có vấn đề gì xảy ra với `$form_state`?
Giuseppe avatar
lá cờ br
@Hudri Tôi sẽ cố gắng viết lại: trong lần chạy đầu tiên của `buildForm`, dữ liệu tôi cần được lấy từ điểm cuối còn lại, nó không nằm trong `$form_state`. Sau đó, tôi lưu trữ dữ liệu đó bên trong `tempstore` (nhưng tôi cũng có thể sử dụng `$form_state->setTemporaryValue()`. Trong các lần gọi lại ajax sau, dữ liệu có thể được truy cập thông qua `$form_state`, nhưng rõ ràng là tôi cần phân biệt giữa trường hợp đầu tiên và những trường hợp tiếp theo.
lá cờ ru
Tôi tin rằng bạn không nhìn thấy gỗ của tất cả các cây :-) Mã giả `function buildForm() { if (!$form_state->get('some_helper_var') { $tempStore = load_external_stuff(); $form_state-> set('some_helper_var', TRUE); } $form['field_foo']['default_value'] = $form_state->get('field_foo') ?? $tempStore->get('foo')); }`
Giuseppe avatar
lá cờ br
@Hudri yeah, tôi không thể thấy giải pháp đó: facepalm: Tuy nhiên, bây giờ tôi đang thử nó, `buildForm` được gọi hai lần trong quá trình gọi lại ajax - ít nhất là trong khi gỡ lỗi. Lần đầu tiên các giá trị trạng thái biểu mẫu trống, vì vậy "nội dung bên ngoài" vẫn được tải mọi lúc, vì vậy nó không thực sự hoạt động :-(
Điểm:5
lá cờ cn

Vì Drupal 8, đối tượng biểu mẫu được khởi tạo bằng buildForm() không được giữ nguyên giữa yêu cầu hiển thị biểu mẫu và yêu cầu Ajax đầu tiên. Vì vậy, hãy chuẩn bị rằng buildForm() được gọi lại và phải tạo ra kết quả chính xác như vậy. Khi bạn lấy dữ liệu từ $form_state, đây không phải là dữ liệu bạn mong đợi từ buildForm() đầu tiên vì dữ liệu này không bao giờ được lưu vào bộ nhớ đệm. Thêm vào sự phức tạp, kết quả hiển thị của bản dựng đầu tiên được lưu vào bộ đệm, do đó, những gì bạn lưu trữ trong bản dựng đầu tiên ở nơi khác, chẳng hạn như trong tempStore, có thể bị lỗi thời trong yêu cầu Ajax. Dữ liệu duy nhất hoạt động như mong đợi là các giá trị biểu mẫu, dữ liệu này có thể bị ẩn nếu bạn muốn có chúng trong biểu mẫu đã gửi và không hiển thị cho người dùng.

TLDR: buildForm() được gọi thường xuyên hơn bạn nghĩ và bạn không nên đặt mã vào đó vì tốn kém để chạy. Tái cấu trúc lệnh gọi API bên ngoài tới một dịch vụ, với bộ nhớ đệm phù hợp, để tần suất được gọi không quan trọng. Làm mất hiệu lực bộ nhớ cache của dịch vụ theo cách giống như biểu mẫu được kết xuất để cả hai bộ đệm đều không có dữ liệu lỗi thời.

Giuseppe avatar
lá cờ br
1. cảm ơn bạn đã giải thích, mặc dù nó không thực sự rõ ràng với tôi. Ví dụ. Tôi không hiểu làm thế nào dữ liệu được lưu trữ trong tempStore có thể bị lỗi thời, nếu $form_state không được lưu vào bộ nhớ cache và mối quan hệ của kết quả được hiển thị trong bộ nhớ cache với điều đó. Có tài liệu chi tiết hơn về cách thức hoạt động của nó để hiểu rõ hơn không?
Giuseppe avatar
lá cờ br
2."Làm mất hiệu lực bộ nhớ cache của dịch vụ theo cách giống như biểu mẫu được kết xuất để cả hai không có dữ liệu lỗi thời." Làm thế nào có thể làm điều đó? Điều gì sẽ là "trình kích hoạt" để làm mất hiệu lực bộ đệm dịch vụ? Ý tôi là, tôi muốn làm điều đó khi tải lại trang, tôi có nên sử dụng `KernelEvents::REQUEST` để tìm tuyến đường cụ thể đó không? Và đối với bộ đệm của biểu mẫu, điều đó có nghĩa là tôi chỉ cần làm cho biểu mẫu không thể lưu vào bộ đệm?
4uk4 avatar
lá cờ cn
1. Vấn đề chính là bạn đang cố sử dụng buildform() ngoài phạm vi. Với cùng một đầu vào, nó phải tạo ra cùng một kết quả thường xuyên như Drupal đang gọi phương thức này. Chỉ khi $form_state chứa các giá trị biểu mẫu đã gửi và đã xử lý hoặc một phần tử kích hoạt thì bạn mới có thể xây dựng lại một $form khác và lưu trữ dữ liệu.
4uk4 avatar
lá cờ cn
2. Thêm ngăn bộ đệm vào dịch vụ và bộ đệm có cùng siêu dữ liệu bộ đệm mà bạn đã đính kèm vào biểu mẫu $ được kết xuất.
4uk4 avatar
lá cờ cn
Nếu điều quan trọng là bạn phải sử dụng cùng một phiên bản của dữ liệu API bên ngoài, thì bạn có thể thêm một chuỗi phiên bản làm phần tử biểu mẫu ẩn.

Đă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.