하나의 엔티티 양식을 다른 엔티티 양식에 임베드하고 둘 다 저장


9

사용자 엔터티에 따라 사용자 지정 엔터티가 있습니다. 실제로, 사용자 프로필 양식 내에 엔터티 양식을 표시하는 것이 합리적이라고 생각한 경우에도 마찬가지입니다.

여기에 이미지 설명을 입력하십시오

내가 지금 가지고있는 문제는 다음과 같습니다. 2 개의 저장 버튼이 있습니다. 그리고 그것이 나쁘지 않으면, 사용자 (아래쪽)의 저장 버튼은 더 이상 작동하지 않으며 화이트 라벨 저장 버튼은 화이트 라벨 엔티티 만 저장합니다.

양식은 다음과 같이 사용자 양식으로 변경됩니다.

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),
  );
}

$whitelabel_formDrupal 7에서 작동했던 배열의 일부 매개 변수를 섞고 싶었지만 그 배열이 엄청 나서 필요한 제출 버튼과 처리기를 찾을 수 없었습니다.

문제는 이것이 가능합니까? 그리고 권장되는 방법은 무엇입니까?



고마워, 나는 실제로 그 질문을 일찍 읽었지만 시도한 것이 무엇이든 그것을 찾을 수 없었습니다. 내가 볼게요
Neograph734

@Eyal, 양식을 재정의하지 않아도되는 방법을 알고 있습니까? 사용자 양식을 그대로 유지하고 싶습니다.
Neograph734

커스텀 모듈 entity_reference_form을 작성했지만 충분히 유지되지 않았습니다. 사용자 정의 코드를 피하려면 inline_entity_form을 사용해야합니다.
Eyal

@Eyal, 사용자 정의 코드를 두려워하지 않습니다 (모듈을 작성 중입니다 : p). 그러나 귀하의 예에서는 더 이상 사용자 양식이 아닌 다중 양식을 작성합니다. 즉, 다른 모듈에서 다른 사람이 동일한 트릭을 시도 할 때마다 항상 3 개 이상의 2 개 양식 중 2 개만 볼 수 있습니다. 그것이 나를 생각 나게하는 것입니다. 하지만 시간을 내 주셔서 감사합니다. 나는 2 일 안에 인라인 엔터티 양식을 다시 살펴볼 것이지만 어떻게 든 변경에 대한 대안을 열 수 있습니다.
Neograph734

답변:


10

자신의 일을하려고하는 대신 인라인 엔터티 양식 모듈을 사용해보십시오 . 이 모듈은이 특정한 경우를 위해 만들어졌습니다 (엔터티 폼 내에서 엔터티 생성 / 편집).

Drupal Commerce의 워크 플로를 개선하기 위해이 작업에 많은 작업을 수행했음을 잘 알고 있습니다. 나는 그것을 직접 테스트하지는 않았지만 Drupal Commerce는 Drupal 8에서도 의존하기 때문에 이미 안정적이어야합니다.

이 모듈은 폼을 생성하는 엔티티 참조 필드에 위젯을 추가하여 작동하므로 플러그 앤 플레이 방식이 매우 중요합니다. 유일한 요구 사항은 사용자에게 사용자 지정 엔터티에 대한 참조가 있어야한다는 것입니다.


나는 그것을 조사했지만 참조 된 엔터티 양식이 나타나지 않았습니다. 그래도 그건 내 실수
일지도 모른다

인라인 엔터티 양식에서 모든 엔터티를 지원하는 것은 아닙니다. 사용자 지정 엔터티 인 경우 사용자 지정 유형 엔터티에 대한 플러그인을 작성해야합니다. 파일 엔티티는 기본적으로 지원되지 않으며이를 필요로합니다.
Frank Robert Anderson

7

나는 이것이 가능해야한다고 믿는다. 불행히도 오늘 코드를 작성할 시간이 없지만 다음 사항을 명심해야합니다.

  • 하위 양식을 추가하는 동안 제출 된 양식을 인식하기 위해 Drupal form_id과 같은 특수 항목을 제거해야합니다 form_build_id.
  • 두 번째 양식의 양식 단추를 원하지 않으면 unset($sub_form['actions'])하위 양식을 기본 양식에 추가하기 전에 양식 양식을 제거해야합니다 .
  • #treePOST 변수에서 별도의 포켓에있는 하위 양식 값을 잡을 수 있도록 양식 을 활성화해야합니다 . 예를 들어 $form['#tree'] = TRUE; $form['sub-form'] = $sub_form; 하위 양식 값을에서 사용할 수있게됩니다 $form_state['values']['sub-form'].
    • 사용자가 하위 양식을 독립적으로 제출할 수있게하려면 나중에 어떤 버튼을 클릭했는지 인식 할 수 있도록 하위 양식에 대한 조치의 이름을 바꾸어야합니다. 사용자가 하나의 저장 버튼 만 사용하여 두 가지를 모두 저장하게하려면 문제가 덜 발생하므로이 하위 지점을 무시하십시오.
  • 이제 UI에 양식이 표시되므로 다음 단계는 제출을 처리하는 것입니다. 이렇게하려면 기본 양식에 양식 제출 콜백 을 추가 하십시오. 하위 양식의 유효성 검사 콜백을 기본 양식에 추가 할 수도 있습니다. 사용자 정의 콜백에서 하위 양식에 대한 제출 콜백을 트리거해야합니다. Drupal 7에서는 drupal_form_submit 을 사용했습니다 . Drupal 8과 같은 기능은 아직 없습니다. 또는 최악의 시나리오에서 하위 양식의 제출 콜백을 수동으로 트리거 할 수 있지만 sub-form값만 전달해야합니다 $form_state['values'](내가 의미하는 바를 이해하십시오).
  • 하위 양식 콜백이 오류없이 작동하면 두 양식이 모두 제출되고 처리되었다고 가정 할 수 있습니다.

그것이 도움이되기를 바랍니다! 실험의 지옥 같은 소리! 행운을 빕니다.


1
감사합니다. 포럼에 초기 코드가 이미 표시되었습니다. 분리 form_build_id, form_token, form_idactions버튼을 만들어 사라지고 다시 '외형'작업을했다. 이걸로 더 연주하고 어떻게 작동하는지 알려 드리겠습니다.
Neograph734

질문에 대답하는 가장 좋은 시도이기 때문에 현상금을 수여합니다. 양식이 '트리 모드'에 들어가기를 거부하기 때문에 여전히이 문제로 어려움을 겪고 있습니다. 모든 값은 내가 무엇을 시도하든 항상 최상위에 저장됩니다. 제출 된 값도 포함되어 있지 않습니다 $form_state ['values'](양식 요소 키가 비어 있음). 아마도 가능하지는 않지만 언젠가 이것을 알아 내고 싶습니다.
Neograph734

1

이론적 대답 (작동하지 않지만 이것이 가장 가깝습니다). 참조를 위해 여기에 게시하고 다른 사람들을위한 출발점.

사용자 양식을 변경하십시오.

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';
}

제출 핸들러 :

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.
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.