¿Es posible mostrar un Formulario de widget de campo en funcionamiento por sí solo?


21

Estoy interesado en incrustar un formulario de widget de campo fuera del contexto del formulario de edición de nodo completo.

He mostrado formularios completos en el pasado usando drupal_get_form pero eso no parece aplicarse a formularios de campo solitarios.

¿Es posible mostrar un formulario de widget de campo en funcionamiento? ¿Cuál sería la mejor manera de hacerlo?

Tanto los widgets de campo como los formularios "normales" se parecen mucho, así que si esto no es posible, ¿qué se requeriría para "cambiar" un formulario de widget a un formulario normal?

Esta pregunta parece estar pidiendo algo similar, pero no entiendo la respuesta. Esa respuesta especifica el uso de hook_field_widget_form_alter ; lo que no entiendo es cómo hacer que se muestre el Formulario de campo, no cómo engancharlo una vez que se está creando.

Respuestas:


18

VBO hace algo como esto en 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);  

Por lo tanto, necesita el tipo de entidad, la entidad (que puede ser un objeto en blanco con solo el conjunto de claves de paquete, eso es lo que realmente se usa), el formulario donde se agregan los widgets y el idioma. Si desea incrustar los widgets más profundamente en el formulario (no en $ form, sino en $ form [$ form_key] como lo hice yo, o incluso más profundo), entonces esa matriz de formularios debe tener #parents establecidos.

Por supuesto, tenga en cuenta que esto incorporará los widgets de todos los campos que pertenecen a ese tipo de entidad y paquete. Así es como se escribieron las funciones de adjuntar. Dar la vuelta a eso requeriría reinventar bastante código; Vea el código real que hace el trabajo pesado. Lo que hago es pasar por instancias de campo, obtener cada $ field_name, y si ese tipo de campo no me interesa, configuro lo $form[$form_key][$field_name]['#access'] = FALSE; que oculta esos widgets de la vista.

EDITAR: De acuerdo, ctools tiene ctools_field_invoke_field () que en teoría podría permitirle trabajar en cada campo. Aunque nunca lo he usado. El texto anterior es mi experiencia directa.


Impresionante respuesta. Pasé la mayor parte del día trabajando con esto, y funcionó como quería. Recompensa otorgada, y recomiendo que el OP acepte esto como la respuesta correcta. Terminé creando un tipo de contenido ficticio para poder controlar mis campos como cualquier otro tipo de contenido, en lugar de configurar lo #access = FALSEque parecía hacky en este contexto.
Letharion

Gracias por confirmar lo que temía: que el widget de campo único no sea prácticamente utilizable por sí solo.
SMTF

7

Estaba usando intensamente la función sugerida por ttk, pero creo que una actualización reciente arruinó las cosas ...

Aquí hay una nueva versión de la solución anterior que funciona bien con Drupal 7.22 y ctools 7.x-1.3.

Entonces, como en la publicación anterior, llama a su función personalizada de esta manera:

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

Observe que el paquete de entidades ahora es un parámetro. Hice esto porque también estaba usando esta función para editar usuarios. De esta manera, también se puede usar para el término de taxonomía, o cualquier otra entidad.

Y el my_field_attach_formse define como:

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

Esta función me ahorró mucho tiempo, ¡espero que también lo haga para usted!


5

Aquí está la solución usando el ctools_field_invoke_field()método. En su función de formulario personalizado, agregue:

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

donde la my_field_attach_formfunción se define como

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

Tenga en cuenta que su sitio necesita tener ctools habilitado. Es una pena que Drupal no incluya una función auxiliar como esta de forma predeterminada.


2

No pude hacer que el método ctools funcionara y decidí hacerlo de esta manera.

Este código estaría dentro de una función de formulario, por lo que $ form y $ form_state ya se pasarían.

function form_function($form, &$form_state) {

Primero cree un nodo vacío de un tipo que tenga el campo que desea representar.

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

Dupliqué las variables de forma para no golpear el original.

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

Saque el campo que está buscando y agréguelo al formulario.

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

Utilicé este método para representar el widget de selección de taxonomía, el widget de casillas de verificación de taxonomía y el widget de selección jerárquica en un formulario personalizado. (El widget de autocompletar taxonomía se procesa pero arroja un error al enviar)

Finalmente renderizar e imprimir

drupal_render(drupal_get_form("form_function"))

Esta parece ser una manera fácil de usar un widget de campo en un formulario personalizado. Sin embargo, depende de un paquete existente. En mi caso, uso un tipo de contenido ficticio donde creo y configuro campos según sea necesario. Eso es un poco hacky pero necesario para los otros métodos también. Solo para tener en cuenta: el ctools_field_invoke_field()método descrito anteriormente también funciona.
Bernhard Fürst

0

He creado formularios a partir de campos individuales usando

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

Esto debería devolver el formulario de widget requerido que se puede utilizar en cualquier forma como

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

Para obtener los valores para los 2 parámetros anteriores, use:

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

Para otros parámetros, puede consultar el enlace de la API aquí

Esto devuelve el formulario de widget predeterminado definido en el campo de tipos de contenido.

Espero que esto ayude a alguien :)

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.