Nhúng một hình thức thực thể vào một hình thức khác và lưu cả hai


9

Tôi có một thực thể tùy chỉnh, đó là tùy thuộc vào thực thể người dùng. Trên thực tế, thậm chí còn tùy thuộc vào việc tôi cảm thấy việc hiển thị biểu mẫu thực thể của mình trong biểu mẫu hồ sơ người dùng là điều hợp lý:

nhập mô tả hình ảnh ở đây

Vấn đề tôi đang gặp phải là như sau; Có 2 nút lưu. Và nếu nó không đủ tệ, nút lưu cho người dùng (nút dưới) thậm chí không hoạt động nữa và nút lưu nhãn trắng chỉ lưu thực thể nhãn trắng.

Biểu mẫu được thay đổi thành biểu mẫu người dùng như thế này:

function whitelabel_form_user_form_alter(&$form, FormStateInterface $form_state) {

  $whitelabel = WhiteLabel::load(1);

  $whitelabel_form = \Drupal::service('entity.manager')
    ->getFormObject('whitelabel', 'default')
    ->setEntity($whitelabel);

  $form['whitelabel'] = array(
    '#type' => 'details',
    '#title' => t('White label settings'),
    '#open' => TRUE,
    'form' => \Drupal::formBuilder()->getForm($whitelabel_form),
  );
}

Tôi đã hy vọng xáo trộn một số tham số trong $whitelabel_formmảng (đã từng hoạt động trong Drupal 7), nhưng mảng đó rất lớn và tôi không thể tìm thấy các nút gửi và trình xử lý mà tôi cần.

Vì vậy, câu hỏi là, điều này có thể được thực hiện? Và cách làm được đề nghị là gì?



Cảm ơn, tôi thực sự đã đọc câu hỏi đó sớm hơn nhưng không có vấn đề gì, tôi không thể tìm thấy nó. Tôi sẽ có một cái nhìn
Neograph734

@Eyal, bạn có biết một phương pháp không yêu cầu tôi ghi đè biểu mẫu không? Tôi muốn giữ hình thức người dùng như nó là.
Neograph734

Tôi đã viết một mô-đun tùy chỉnh entity numference_form nhưng nó không được duy trì đủ. Bạn có thể nên sử dụng inline_entity_form nếu bạn muốn tránh mã tùy chỉnh.
Mắt

@Eyal, tôi không sợ mã tùy chỉnh (Tôi đang viết một mô-đun: p). Nhưng trong ví dụ của bạn, bạn tạo ra một dạng đa dạng không còn là dạng người dùng. Điều này có nghĩa là bất cứ khi nào người khác cố gắng thực hiện cùng một thủ thuật trong một mô-đun khác, bạn sẽ luôn chỉ thấy 2 trong số 3 (hoặc nhiều hơn) các biểu mẫu có sẵn. Đó là những gì tôi nghĩ. Nhưng cảm ơn vì đã dành thời gian để quay lại với tôi. Tôi sẽ có một cái nhìn khác về hình thức thực thể nội tuyến trong 2 ngày, nhưng tôi sẽ mở cho các lựa chọn thay thế trong việc thay đổi nó trong một số cách.
Neograph734

Câu trả lời:


10

Thay vì cố gắng làm việc của riêng bạn, bạn nên thử mô-đun Inline Entity Form . Mô-đun này được tạo cho trường hợp cụ thể này (tạo / chỉnh sửa các thực thể trong các biểu mẫu thực thể).

Tôi biết rất nhiều công việc đã được đưa vào để cải thiện quy trình làm việc trong Drupal Commerce, điều này có nghĩa là điều này sẽ hoạt động tốt. Tôi đã không tự mình kiểm tra, nhưng vì Drupal Commerce cũng phụ thuộc vào nó trong Drupal 8, nên nó đã khá ổn định rồi.

Mô-đun hoạt động bằng cách thêm một tiện ích vào trường tham chiếu thực thể tạo biểu mẫu, vì vậy nó sẽ được cắm và phát khá nhiều. Yêu cầu duy nhất là người dùng có một tham chiếu đến thực thể tùy chỉnh của bạn.


Tôi đã xem xét điều đó, nhưng hình thức thực thể được tham chiếu đã không xuất hiện. Đó có thể là một lỗi về phía tôi mặc dù ...
Neograph734

Không phải tất cả các thực thể đều được hỗ trợ bởi Biểu mẫu thực thể nội tuyến, nếu đây là một thực thể tùy chỉnh thì bạn sẽ cần phải viết một plugin cho các thực thể thuộc loại tùy chỉnh của mình. Các thực thể tệp không được hỗ trợ theo mặc định và yêu cầu này.
Frank Robert Anderson

7

Tôi tin rằng điều này nên có thể. Thật không may, tôi không có thời gian để viết mã ngày hôm nay, tuy nhiên, tôi nghĩ bạn nên ghi nhớ những điều sau:

  • Trong khi nối thêm biểu mẫu con, hãy đảm bảo bạn xóa các mục đặc biệt như form_idform_build_idđược Drupal sử dụng để nhận ra biểu mẫu nào đã được gửi.
  • Nếu bạn không muốn các nút biểu mẫu ở dạng thứ hai, bạn cần xóa mục biểu mẫu đó như unset($sub_form['actions'])trước khi bạn thêm biểu mẫu phụ vào biểu mẫu chính.
  • Đảm bảo rằng bạn kích hoạt #treebiểu mẫu để bạn có thể bắt các giá trị của biểu mẫu con trong một túi riêng biệt trong biến POST. Ví dụ, $form['#tree'] = TRUE; $form['sub-form'] = $sub_form; Điều này sẽ làm cho các giá trị biểu mẫu con của bạn có sẵn trong $form_state['values']['sub-form'].
    • Nếu bạn muốn người dùng có thể gửi biểu mẫu phụ một cách độc lập, bạn sẽ phải đổi tên các hành động cho biểu mẫu phụ để sau này bạn có thể nhận ra nút nào được nhấp. Nếu bạn muốn người dùng chỉ sử dụng một nút lưu để lưu cả hai thứ, thì sẽ có ít rắc rối hơn nên bỏ qua điểm phụ này.
  • Bây giờ, biểu mẫu được hiển thị trong giao diện người dùng, bước tiếp theo sẽ là xử lý việc gửi. Để làm điều này, hãy thêm một cuộc gọi lại biểu mẫu vào biểu mẫu chính của bạn. Bạn cũng có thể muốn thêm các cuộc gọi lại xác thực của biểu mẫu phụ vào biểu mẫu chính. Trong cuộc gọi lại tùy chỉnh, bạn sẽ phải kích hoạt cuộc gọi lại gửi cho biểu mẫu con. Trong Drupal 7, chúng tôi đã từng sử dụng drupal_form_submit - Tôi chưa biết tương đương với Drupal 8. Ngoài ra, bạn có thể kích hoạt các cuộc gọi lại gửi biểu mẫu phụ theo cách thủ công trong trường hợp xấu nhất, nhưng hãy đảm bảo bạn chỉ chuyển các sub-formgiá trị trong $form_state['values'](hy vọng bạn hiểu ý tôi muốn nói).
  • Khi gọi lại biểu mẫu con hoạt động mà không có lỗi, bạn có thể giả sử cả hai biểu mẫu đã được gửi và xử lý thành công!

Hy vọng nó giúp! Âm thanh như một địa ngục của một thí nghiệm! Chúc may mắn.


1
Cảm ơn, tôi đã nhận được diễn đàn để hiển thị với mã ban đầu của tôi. Loại bỏ form_build_id, form_token, form_idactionslàm nút biến mất và làm công việc 'hình thức bên ngoài' một lần nữa. Tôi sẽ chơi với cái này thêm nữa và cho bạn biết nó hoạt động ra sao.
Neograph734

Tôi đang trao thưởng cho bạn tiền thưởng vì đó là nỗ lực tốt nhất để trả lời câu hỏi. Tôi vẫn đang vật lộn với điều này vì hình thức từ chối chuyển sang 'chế độ cây'. Tất cả các giá trị luôn được lưu trữ ở cấp cao nhất cho dù tôi có cố gắng gì. Và có vẻ như các giá trị được gửi cũng không nằm trong $form_state ['values'](các khóa phần tử biểu mẫu trống). Có lẽ là không thể (chưa), nhưng tôi hy vọng sẽ tìm ra điều này vào một ngày nào đó.
Neograph734

1

Câu trả lời lý thuyết (một câu trả lời không hoạt động, nhưng đây là câu trả lời gần nhất tôi có). Đăng ở đây để tham khảo và một điểm khởi đầu cho những người khác.

Thay đổi hình thức người dùng.

function whitelabel_form_user_form_alter(&$form, FormStateInterface $form_state) {
  $whitelabel = WhiteLabel::load(1);

  $whitelabel_form = \Drupal::entityTypeManager()
    ->getFormObject('whitelabel', 'default')
    ->setEntity($whitelabel);
  $renderable_form = \Drupal::formBuilder()->getForm($whitelabel_form);

  // Remove embedded form specific data.
  unset($renderable_form['actions']);
  unset($renderable_form['form_build_id']);
  unset($renderable_form['form_token']);
  unset($renderable_form['form_id']);

  // Also remove all other properties that start with a '#'.
  foreach ($renderable_form as $key => $value) {
    if (strpos($key, '#') === 0) {
      unset ($renderable_form[$key]);
    }
  }

  // Create a container for the entity's fields.
  $form['whitelabel'] = array(
    '#type' => 'details',
    '#title' => t('White label settings'),
    '#open' => TRUE,
    '#tree' => TRUE,
  );
  $form['whitelabel'] += $renderable_form;

  $form['actions']['submit']['#submit'][] = 'whitelabel_form_user_form_submit';
}

Trình xử lý:

function whitelabel_form_user_form_submit(&$form, FormStateInterface $form_state) {
  $values = $form_state->getValues(); 

  $form_state = new FormState();
  $form_state->setValues($values);
  // Theoretically you'd want to use $values['entity_container']
  // for the dedicated entity values.

  // Obtain or create an entity. (You want to get this from the form.)
  if (!$whitelabel = WhiteLabel::load(1)) {
    $whitelabel = WhiteLabel::create();
  }

\Drupal::entityTypeManager()
  ->getFormObject('whitelabel', 'default')
  ->setEntity($whitelabel) // Current entity.
  ->buildEntity($form, $form_state) // Update with form values.
  ->save(); // Save updated entity.
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.