Appels AJAX dans le plug-in de type de contenu CTools?

10

Je crée un type de contenu de panneaux CTools (c'est-à-dire la chose que vous insérez dans les panneaux lors de l'ajout de contenu, pas un type de nœud) et j'essaie d'utiliser l' #ajaxattribut d' un élément de formulaire pour définir des valeurs par défaut. Voir le code ci-dessous.

my_module_content_type_edit_form($form, &$form_state)Soit dit en passant, tout cela se trouve à l'intérieur de l' appel du type de contenu .

  $form['link_type'] = array(
    '#type' => 'radios',
    '#title' => t('Link Type'),
    '#ajax' => array(
      'callback' => 'my_module_set_target'
    ),
    '#default_value' => empty($conf['link_type']) ? '_blank' : $conf['link_type'],
    '#options' => array('none'=>t('No Link'), 'internal'=>t('Internal Link'), 'external'=>t('External Link'), 'document'=>t('Document Link')),
  );

Mon rappel est le suivant.

function my_module_set_target($form, $form_state) {
  watchdog("Test", "Testing callback", array(), WATCHDOG_ALERT);
  $form['link_target']['#default_value'] = '_parent';

  return $form['link_target']['#default_value'];
}

Peu importe si le retour que je watchdog()propose fonctionnerait, ne fonctionne même pas.

Je sais que CTools fait des trucs bizarres avec AJAX, mais ça ne peut pas être si bizarre. Avez-vous une idée de la façon dont je ferais ce que je veux faire?

Merci!

Alternativement: Comment définir une valeur par défaut basée sur la valeur d'une option de formulaire précédente?

J'ai compris comment faire cela, mais c'est un peu hacky - vous créez de nouveaux champs de formulaire pour chaque fourchette de dépendance. Vous pouvez ensuite fusionner les valeurs dans hook_content_type_edit_form_submit(), en utilisant celle qui correspond à la valeur choisie pour le composant qui a initialement tout forké.

Je laisse la question ouverte parce que moi (et, franchement, tous les programmeurs avec qui je travaille), je veux vraiment un bon moyen d'utiliser AJAX dans ces formulaires de modification de type de contenu de Panel.

Mise à jour: Il semble que vous ne puissiez pas non plus faire de trucs avec #attached.

$form['link'][$i] = array(
  '#type' => 'fieldset',
  '#title' => t('Link #@num', array('@num' => $i)),
  '#collapsible' => TRUE,
  '#collapsed' => TRUE,
  '#attached' => array(
    'js' => array(
      'alert("Yay.");', 'inline'
    ),
  )
);
aendrew
la source
Étant un développeur de Drupal de type "Panels for everything", j'imagine que je pourrais aussi trouver une utilisation à l'avenir, alors j'ai ajouté une prime, permet de voir ce qui se passe.
Letharion
Wow, cette prime est allée et vient sans même un commentaire (Merci BTW, Letharion). Est-ce que ce que je demande est impossible ou quelque chose?
aendrew
Il convient de noter que j'ai réussi à ajouter Javascript à l'aide de ctools_add_js();ou drupal_add_js();à la fin de hook_content_type_edit_form();. Si vous faites simplement des trucs simples liés à l'interface utilisateur, cela semble être le meilleur appel (au moins jusqu'à ce que quelqu'un réponde correctement à cette question).
aendrew

Réponses:

8

Réponse courte: vous devez utiliser #ajax ['chemin'].

Longue réponse:

Avoir un rappel ajax n'aide pas car ctools crée ses formes différemment afaik. Le rappel effectué par system / ajax ne peut pas trouver la définition complète du formulaire et ne peut donc pas trouver un élément pour traiter la demande ajax. L'utilisation de #ajax [chemin] déclenche simplement un élément de menu.

Vous pouvez vérifier par vous-même en vidant le formulaire lorsque vous utilisez #ajax [rappel]

function ajax_form_callback() {
  list($form, $form_state) = ajax_get_form();
  drupal_process_form($form['#form_id'], $form, $form_state);

J'ai modifié le simplecontext_content_type_edit_form en ajoutant le widget de saisie semi-automatique de l'utilisateur et votre champ qui fonctionnent tous les deux :)

function simplecontext_content_type_edit_form($form, &$form_state) {
  $conf = $form_state['conf'];

  $form['owner_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Username'),
    '#default_value' => 'admin',
    '#autocomplete_path' => 'user/autocomplete',
    '#size' => '6',
    '#maxlength' => '60',
    '#description' => '$description',
  );

  $form['link_type'] = array(
    '#type' => 'radios',
    '#title' => t('Link Type'),
    '#ajax' => array(
      'path' => 'my_module_set_target'
    ),
    '#default_value' => empty($conf['link_type']) ? '_blank' : $conf['link_type'],
    '#options' => array('none' => t('No Link'), 'internal' => t('Internal Link'), 'external' => t('External Link'), 'document' => t('Document Link')),
  );
...

Comme vous utilisez maintenant le chemin #ajax, vous devez ajouter un élément de menu comme je l'ai aimé

<?php

function my_module_menu() {
  $items = array(
    'my_module_set_target' => array(
      'title' => 'AJAX Example',
      'page callback' => 'my_module_set_target',
      'access callback' => TRUE,
      'expanded' => TRUE,
    )
  );
  return $items;
}

function my_module_set_target() {
  drupal_json_output( array('data' => "ABC"));
}

Un nittpick sur #attached [js]: le js en ligne doit être clé => valeur comme:

'#attached' => array(
  'js' => array(
    'alert("Yay.");' => 'inline',
  ),
),

J'ai utilisé Firebug pour vérifier la valeur résultante et non l'effet résultant. J'espère donc que cela vous aidera à résoudre votre problème.

Clemens Tolboom
la source
Sensationnel. Je suis tellement content d'avoir enfin une réponse à cette question. Je vais l'essayer dans un instant. Merci également pour la note sur le bit # attaché, c'est en fait ce que j'avais initialement (mais je l'ai changé parce que je pensais que cela ne pouvait pas être correct).
aendrew
Alors, un succès? Serait intéressant de savoir avant la fin de la prime :)
Letharion
J'espère obtenir ma prime: p
Clemens Tolboom
Désolé pour le retard avec cela, ayant un peu de temps pour le faire fonctionner - lorsque j'essaie de retourner le tableau $ form, il me dit que ma fonction de validation n'est pas définie. C'est le cas, et lorsque j'essaye de le déclarer à nouveau dans mon module (par opposition au fichier de plugin de type de contenu), il me dit que je le redéclare. Je suppose que ce n'est pas ce que je dois faire, mais je ne peux pas comprendre comment structurer drupal_json_output afin qu'il génère quelque chose que mon formulaire interprétera comme une réponse significative. De l'aide? Un meilleur exemple de rappel aiderait beaucoup. Merci!
aendrew
J'ai manqué la toute petite partie de votre question qui concerne la valeur de retour : return $ form ['link_target'] ['# default_value']; qui est votre tentative de retourner un formulaire drupal dans un contexte html / javascript . Ça ne marchera pas. Avez-vous vu quelque chose de similaire ce que vous voulez dans l'interface utilisateur des panneaux? (Je désactive moi-même JavaScript de temps en temps avec l'interface utilisateur des vues juste pour voir le flux de travail non js) (modifié ce commentaire un million de fois ... maladroit)
Clemens Tolboom
2

J'ai eu un problème similaire, où je voulais inclure un type d'élément Media dans un plugin de type de contenu CTools, qui utilise également ajax pour sélectionner une image.

Il utilise son propre paramètre ajax 'path', au lieu du paramètre 'callback', mais lors de la sélection d'une image, le formulaire a été reconstruit sans l'élément multimédia.

J'ai tracé cela au fait que drupal_rebuild_form ne pouvait trouver ni la fonction wrapper de formulaire CTools, ni la fonction de formulaire de paramètres réels. Je l'ai donc corrigé en ajoutant ces lignes de code au formulaire de paramètres ctools:

function custom_module_my_content_plugin_content_type_edit_form($form, &$form_state) {

$background_image = isset($conf['background_image']) ? $conf['background_image'] : array();
  $form['background_image'] = array(
    '#title' => t('Background image'),
    '#default_value' => $background_image,
    '#type' => 'media',
    '#input' => TRUE,
    '#extended' => TRUE,
    '#tree' => TRUE,
    '#media_options' => array(),
  );

  // The two function calls below are necessary if we want to use a media
  // element type, because it causes ajax requests, which in turn call
  // drupal_form_rebuild(), and without the below includes, Drupal will
  // not be able to rebuild the form.

  // Include the CTools content type plugin file, because it provides
  // the ctools_content_configure_form_defaults() function, which is needed
  // when rebuilding the form, because of an ajax action, like selecting
  // a media element.
  ctools_form_include($form_state, 'content');

  // Include this plugin file as well, so that when the form is rebuilt, it
  // can successfully retrieve the settings form.
  ctools_form_include($form_state, 'my_content_plugin', 'custom_module', 'plugins/content_types/my_content_plugin');

}

Peut-être que je manque quelque chose de pourquoi les fichiers include ne sont pas chargés, mais les inclure manuellement a résolu le problème pour moi.

Placinta
la source
0

de mon côté, j'ai dû écrire une fonction wrapper de formulaire dans un fichier .module et inclure manuellement le volet (où le contenu du formulaire d'origine est défini) comme ça:

function mymodule_form($form, &$form_state) {
  // include mymodule/panes/mypane.inc
  ctools_include('mypane', 'mymodule', 'panes');
  return mymodule_form_content($form, $form_state);
}

Maintenant, pendant l'appel ajax, Drupal est capable de récupérer mon formulaire afin que je puisse utiliser l'API de formulaire AJAX standard.

Pierco
la source