È possibile visualizzare un modulo widget di campo funzionante da solo?


21

Sono interessato a incorporare un modulo per widget di campo fuori dal contesto dell'intero modulo di modifica dei nodi.

In passato ho visualizzato moduli completi usando drupal_get_form ma questo non sembra applicarsi ai moduli di campo solitari.

È possibile visualizzare un modulo widget di campo funzionante? Quale sarebbe il modo migliore per farlo?

Sia i widget di campo che i moduli "normali" sembrano molto simili, quindi se ciò non fosse possibile, cosa sarebbe necessario per "cambiare" un modulo widget in un modulo normale?

Questa domanda sembra chiedere qualcosa di simile ma non capisco la risposta. Quella risposta specifica usando hook_field_widget_form_alter ; ciò che non capisco è come visualizzare il Field Form e non come agganciarlo una volta creato.

Risposte:


18

VBO fa qualcosa del genere in edit.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);  

Pertanto, è necessario il tipo di entità, l'entità (che può essere un oggetto vuoto con solo il set di chiavi del bundle, ecco cosa viene effettivamente utilizzato), il modulo in cui vengono aggiunti i widget e la lingua. Se vuoi incorporare i widget più in profondità nel modulo (non in $ form, ma in $ form [$ form_key] come ho fatto io, o anche più in profondità), allora l'array di moduli deve avere #parents impostato.

Naturalmente, si noti che ciò incorporerà i widget di tutti i campi appartenenti a quel tipo di entità e pacchetto. Ecco come sono state scritte le funzioni di collegamento. Andare in giro richiederebbe di reinventare un bel po 'di codice; vedere il codice effettivo che esegue il sollevamento pesante. Quello che faccio è passare attraverso le istanze del campo, ottenere ogni $ field_name e se quel tipo di campo non mi interessa, ho impostato $form[$form_key][$field_name]['#access'] = FALSE; che nasconde quei widget alla vista.

EDIT: Okay, ctools ha ctools_field_invoke_field () che in teoria potrebbe permetterti di lavorare in base al campo. Non l'ho mai usato però. Il testo sopra è la mia esperienza diretta.


Risposta fantastica. Ho trascorso la maggior parte della giornata a lavorare con questo, e ha funzionato proprio come volevo. Premio Bounty, e raccomando all'OP di accettarlo come risposta corretta. Ho finito per creare un tipo di contenuto fittizio in modo da poter controllare i miei campi come qualsiasi altro tipo di contenuto, invece di impostare ciò #access = FALSEche sembrava confuso in questo contesto.
Letharion,

Grazie per aver confermato ciò che avevo temuto: che il widget a campo singolo non fosse praticamente utilizzabile da solo.
SMTF

7

Stavo usando intensamente la funzione suggerita da ttk, ma penso che un recente aggiornamento abbia incasinato le cose ...

Ecco una nuova versione della soluzione precedente che funziona bene con Drupal 7.22 e ctools 7.x-1.3.

Quindi, come nel post precedente, chiami la tua funzione personalizzata in questo modo:

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

Si noti che il pacchetto entità è ora un parametro. L'ho fatto perché stavo anche usando questa funzione per modificare gli utenti. In questo modo, può anche essere utilizzato per il termine tassonomia o qualsiasi altra entità.

E il my_field_attach_formè definito come:

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

Questa funzione mi ha fatto risparmiare un sacco di tempo, spero lo farà anche per te!


5

Ecco la soluzione usando il ctools_field_invoke_field()metodo Nella tua funzione di modulo personalizzato, aggiungi:

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

dove la my_field_attach_formfunzione è definita come

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

Nota che il tuo sito deve avere abilitato ctools. È un peccato che Drupal non includa una funzione di supporto come questa per impostazione predefinita.


2

Non sono riuscito a far funzionare il metodo ctools e ho deciso di farlo in questo modo.

Questo codice sarebbe all'interno di una funzione form, quindi $ form e $ form_state sarebbero già passati.

function form_function($form, &$form_state) {

Per prima cosa crea un nodo vuoto di un tipo che ha il campo che stai cercando di renderizzare.

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

Ho duplicato le variabili del modulo in modo da non ostruire l'originale.

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

Estrai il campo che stai cercando e aggiungilo al modulo.

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

Ho usato questo metodo per visualizzare il widget di selezione tassonomia, il widget caselle di controllo tassonomia e il widget Selezione gerarchica su un modulo personalizzato. (Il widget di completamento automatico della tassonomia esegue il rendering ma genera un errore durante l'invio)

Finalmente rendering e stampa

drupal_render(drupal_get_form("form_function"))

Questo sembra essere un modo semplice per utilizzare un widget di campo in un modulo personalizzato. Tuttavia, dipende da un pacchetto esistente. Nel mio caso uso un tipo di contenuto fittizio in cui creo e configuro i campi secondo necessità. È un po 'confuso ma necessario anche per gli altri metodi. Solo per notare: funziona anche il ctools_field_invoke_field()metodo sopra descritto.
Bernhard Fürst,

0

Ho creato moduli da campi individuali utilizzando

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

questo dovrebbe restituire il modulo widget richiesto che può essere utilizzato in qualsiasi forma simile

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

Per ottenere i valori per il parametro 2 sopra utilizzare:

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

Per altri parametri è possibile controllare il collegamento API qui

Ciò restituisce il modulo widget predefinito definito nel campo Tipi di contenuto.

Spero che questo aiuti qualcuno :)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.