web-dev-qa-db-fra.com

Est-il possible d'afficher un formulaire de widget de champ de manière autonome?

Je souhaite intégrer un formulaire de widget de champ en dehors du contexte de l'ensemble du formulaire de modification de nœud.

J'ai affiché des formulaires complets dans le passé en utilisant drupal_get_form mais cela ne semble pas s'appliquer aux formulaires de champ solitaires.

Est-il possible d'afficher un formulaire de widget de champ fonctionnel? Quelle serait la meilleure façon de procéder?

Les widgets de champ et les formulaires "normaux" semblent très similaires, donc si cela n'est pas possible, que faudrait-il pour "changer" un formulaire widget en un formulaire normal?

Cette question semble demander quelque chose de similaire mais je ne comprends pas la réponse. Cette réponse spécifie l'utilisation de hook_field_widget_form_alter ; ce que je ne comprends pas, c'est comment afficher le formulaire de champ et non comment le raccorder une fois qu'il est créé.

21
SMTF

VBO fait quelque chose comme ça dans 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);  

Donc, vous avez besoin du type d'entité, de l'entité (qui peut être un objet vide avec juste le jeu de clés de bundle, c'est ce qui est réellement utilisé), du formulaire où les widgets sont ajoutés et de la langue. Si vous souhaitez intégrer les widgets plus profondément dans le formulaire (pas dans $ form, mais dans $ form [$ form_key] comme je l'ai fait, ou même plus profondément), alors ce tableau de formulaires doit avoir #parents défini.

Bien sûr, notez que cela incorporera les widgets de tous les champs appartenant à ce type d'entité et à cet ensemble. C'est ainsi que les fonctions d'attachement ont été écrites. Contourner cela vous obligerait à réinventer pas mal de code; voir le code réel qui fait le gros du travail. Ce que je fais, c'est passer par les instances de champ, récupérer chaque $ field_name, et si ce type de champ ne m'intéresse pas, je mets $form[$form_key][$field_name]['#access'] = FALSE; qui cache ces widgets à la vue.

EDIT: D'accord, ctools a ctools_field_invoke_field () qui pourrait en théorie vous permettre de travailler sur une base par champ. Je ne l'ai jamais utilisé cependant. Le texte ci-dessus est mon expérience directe.

18
Bojan Zivanovic

J'utilisais intensivement la fonction suggérée par ttk, mais je pense qu'une récente mise à jour a gâché les choses ...

Voici une nouvelle version de la solution précédente qui fonctionne bien avec Drupal 7.22 et ctools 7.x-1.3.

Donc, comme dans le post précédent, vous appelez votre fonction personnalisée comme ceci:

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

Notez que l'entité bundle est maintenant un paramètre. Je l'ai fait parce que j'utilisais également cette fonction pour modifier les utilisateurs. De cette façon, il peut également être utilisé pour le terme de taxonomie, ou toute autre entité.

Et le my_field_attach_form est défini comme:

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

Cette fonction m'a fait gagner beaucoup de temps, j'espère qu'elle le sera aussi pour vous!

7
jmcouillard

Voici la solution utilisant la méthode ctools_field_invoke_field(). Dans votre fonction de formulaire personnalisé, ajoutez:

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

où le my_field_attach_form la fonction est définie comme

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

Notez que votre site doit avoir activé les outils ctools. Il est dommage que Drupal n'inclut pas une fonction d'aide comme celle-ci par défaut.

5
ttk

Je n'ai pas réussi à faire fonctionner la méthode ctools et j'ai décidé de le faire de cette façon à la place.

Ce code serait à l'intérieur d'une fonction de formulaire, donc $ form et $ form_state seraient déjà passés.

function form_function($form, &$form_state) {

Créez d'abord un nœud vide d'un type contenant le champ que vous souhaitez rendre.

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

J'ai dupliqué les variables du formulaire pour ne pas encombrer l'original.

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

Retirez le champ que vous recherchez et ajoutez-le au formulaire.

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

J'ai utilisé cette méthode pour rendre le widget de sélection de taxonomie, le widget de cases à cocher de taxonomie et le widget Sélection hiérarchique sur un formulaire personnalisé. (Le widget Taxonomy Autocomplete s'affiche mais génère une erreur lors de la soumission)

Enfin rendre et imprimer

drupal_render(drupal_get_form("form_function"))
2
Scott Joudry

J'ai créé des formulaires à partir de champs individuels en utilisant

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

cela devrait renvoyer le formulaire de widget requis qui peut être utilisé sous n'importe quelle forme comme

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

Pour obtenir les valeurs du paramètre 2 ci-dessus, utilisez:

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

Pour d'autres paramètres, vous pouvez vérifier le lien api ici

Cela renvoie le formulaire de widget par défaut défini dans le champ des types de contenu.

J'espère que cela aide quelqu'un :)

0
akshay daxini