Возможно ли отображение рабочей формы виджета поля самостоятельно?

21

Я заинтересован во внедрении формы виджета поля вне контекста формы редактирования всего узла.

В прошлом я отображал полные формы с использованием drupal_get_form, но это не относится к отдельным полевым формам.

Возможно ли отображение рабочей формы виджета поля? Каков будет лучший способ сделать это?

И виджеты полей, и «нормальные» формы кажутся очень похожими, поэтому, если это невозможно, что потребуется для «изменения» формы виджета на нормальную форму?

Этот вопрос, кажется, задает нечто подобное, но я не понимаю ответа. Этот ответ указывает использование hook_field_widget_form_alter ; я не понимаю, как заставить отображаться форму поля, а не как подключить ее после создания.

SMTF
источник

Ответы:

18

VBO делает что-то подобное в modify.action.inc:

$form_key = 'bundle_' . $bundle_name;
$form[$form_key] = array(
  '#type' => 'fieldset',
  '#title' => $label,
  '#parents' => array($form_key),
);  
field_attach_form($context['entity_type'], $entity, $form[$form_key], $form_state, LANGUAGE_NONE);  

Итак, вам нужен тип сущности, сущность (которая может быть пустым объектом только с набором ключей комплекта, вот что фактически используется), форма, в которую добавляются виджеты, и язык. Если вы хотите встраивать виджеты глубже в форму (не в $ form, а в $ form [$ form_key], как я сделал, или даже глубже), то в этом массиве формы должен быть установлен #parents.

Конечно, обратите внимание, что это будет включать виджеты всех полей, принадлежащих к этому типу сущности и комплекту. Вот как были написаны функции присоединения. Чтобы обойти это, вам придется заново изобретать довольно много кода; увидеть фактический код, который делает тяжелую работу. Что я делаю, так это просматриваю экземпляры полей, получаю каждое $ field_name, и если этот тип поля меня не интересует, я устанавливаю, $form[$form_key][$field_name]['#access'] = FALSE; что скрывает эти виджеты от глаз.

РЕДАКТИРОВАТЬ: Хорошо, ctools имеет ctools_field_invoke_field (), который теоретически может позволить вам работать на основе поля. Я никогда не использовал это все же. Текст выше - мой прямой опыт.

Боян Живанович
источник
Потрясающий ответ. Я провел большую часть дня, работая с этим, и это сработало так, как я хотел. Награда присуждается, и я рекомендую ОП принять это как правильный ответ. Я закончил тем, что создал фиктивный тип контента, чтобы я мог контролировать свои поля, как и любой другой тип контента, вместо настройки, #access = FALSEкоторая казалась хакерской в ​​этом контексте.
Летарион
Спасибо за подтверждение того, чего я боялся: виджет с одним полем практически не может использоваться сам по себе.
SMTF
7

Я интенсивно использовал функцию, предложенную ttk, но я думаю, что недавнее обновление испортило вещи ...

Вот новая версия предыдущего решения, которая хорошо работает с Drupal 7.22 и ctools 7.x-1.3.

Итак, как и в предыдущем посте, вы вызываете свою пользовательскую функцию следующим образом:

my_field_attach_form('field_body', 'node', 'blog',  $node, $form, $form_state, LANGUAGE_NONE);

Обратите внимание, что пакет сущностей теперь является параметром. Я сделал это, потому что я также использовал эту функцию для редактирования пользователей. Таким образом, он также может быть использован для термина таксономии или любого другого субъекта.

И my_field_attach_formопределяется как:

function my_field_attach_form($field_name, $entity_type, $bundle, $entity, &$form, &$form_state, $langcode = NULL) {

  // Set #parents to 'top-level' if it doesn't exist.
  $form += array('#parents' => array());

  // If no language is provided use the default site language.
  $options = array(
    'language' => field_valid_language($langcode),
    'default' => TRUE,
  );

  // Append to the form
  ctools_include('fields');
  $field_instance = field_info_instance($entity_type, $field_name, $bundle);
  $form += (array) ctools_field_invoke_field($field_instance, 'form', $entity_type, $entity, $form, $form_state, $options);
}

Эта функция сэкономила мне много времени, надеюсь, она будет и для вас!

jmcouillard
источник
5

Вот решение с использованием ctools_field_invoke_field()метода. В вашей пользовательской функции формы добавьте:

$form = array();
$node = new stdClass();
$node->type = 'blog';
my_field_attach_form('field_body', 'node', $node, $form, $form_state, LANGUAGE_NONE);

где my_field_attach_formфункция определяется как

function my_field_attach_form($field_name, $entity_type, $entity, &$form, &$form_state, $langcode = NULL) {
  // Set #parents to 'top-level' if it doesn't exist.
  $form += array('#parents' => array());

  // If no language is provided use the default site language.
  $options = array(
    'language' => field_valid_language($langcode),
    'default' => TRUE,
  );
  module_load_include("inc","ctools","includes/fields");
  $form += (array) ctools_field_invoke_field($field_name, 'form', $entity_type, $entity, $form, $form_state, $options);
}

Обратите внимание, что на вашем сайте должен быть включен ctools. Плохо, что Drupal по умолчанию не имеет такой вспомогательной функции.

TTK
источник
2

Я не смог заставить работать метод ctools и решил сделать это таким образом.

Этот код будет внутри функции формы, поэтому $ form и $ form_state уже будут переданы.

function form_function($form, &$form_state) {

Сначала создайте пустой узел типа, который имеет поле, которое вы хотите визуализировать.

    $entity = new stdClass();
    $entity->title = "Temp Object";
    $entity->type = "node_type";
    node_object_prepare($entity);

Я продублировал переменные формы, чтобы не загромождать оригинал.

    $temp_form       = $form;
    $temp_form_state = $form_state;
    field_attach_form("node", $entity, $temp_form, $temp_form_state);

Вытащите поле, которое вы ищете, и добавьте его в форму.

    $form["field"] = $temp_form["existing_field"];
}

Я использовал этот метод для отображения виджета выбора таксономии, виджета флажков таксономии и виджета Иерархический выбор в пользовательской форме. (Виджет таксономии автозаполнения отображается, но выдает ошибку при отправке)

Наконец рендер и печать

drupal_render(drupal_get_form("form_function"))
Скотт Джудри
источник
Это кажется простым способом использовать виджет поля в пользовательской форме. Это зависит от существующего комплекта, хотя. В моем случае я использую фиктивный тип контента, где я создаю и настраиваю поля по мере необходимости. Это немного глупо, но необходимо и для других методов. Просто отметить: ctools_field_invoke_field()описанный выше метод работает также.
Бернхард Фюрст
0

Я создал формы из отдельных полей, используя

field_default_form('entity_type', $entity, $field,$field_instance,LANGUAGE_NONE,$default_value, $form, $form_state);

это должно вернуть требуемую форму виджета, которую можно использовать в любой форме, например

 $custom_form['form_element_to_display'] = field_default_form('entity_type', $entity, $field,$field_instance,LANGUAGE_NONE,$default_value, $custom_form, $custom_form_state);

Чтобы получить значения для параметра 2 выше, используйте:

$field = field_info_field($field_name);
$field_instance = field_info_instance('node', $field_name, $node_type);

Для других параметров вы можете проверить ссылку API здесь

Это возвращает форму виджета по умолчанию, определенную в поле типов контента.

Надеюсь, это поможет кому-то :)

Акшай Даксини
источник