AJAX ruft das CTools Content Type Plugin auf?

10

Ich erstelle einen Inhaltstyp für CTools-Bedienfelder (dh das Element, das Sie beim Hinzufügen von Inhalten in Bedienfelder einfügen, nicht einen Knotentyp) und versuche, das #ajaxAttribut eines Formularelements zu verwenden, um einige Standardwerte festzulegen. Siehe Code unten.

Dies ist my_module_content_type_edit_form($form, &$form_state)übrigens alles innerhalb des Aufrufs des Inhaltstyps .

  $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')),
  );

Mein Rückruf ist der folgende.

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'];
}

Unabhängig davon, ob die von mir vorgeschlagene Rückkehr tatsächlich funktionieren würde, watchdog()funktioniert sie nicht einmal.

Ich weiß, dass CTools einige seltsame Dinge mit AJAX macht, aber es kann nicht so seltsam sein. Haben Sie eine Idee, wie ich tun würde, was ich tun möchte?

Vielen Dank!

Alternativ: Wie setze ich einen Standardwert basierend auf dem Wert einer vorherigen Formularoption?

Ich habe herausgefunden, wie das geht, aber es ist ein bisschen hacky - Sie erstellen neue Formularfelder für jede Abhängigkeitsgabel. Sie können dann die Werte zusammenführen hook_content_type_edit_form_submit(), wobei der Wert verwendet wird, der dem Wert entspricht, der für die Komponente ausgewählt wurde, die anfangs alles gegabelt hat.

Ich lasse die Frage offen, weil ich (und ehrlich gesagt jeder Programmierer, mit dem ich arbeite) wirklich eine gute Möglichkeit haben möchte, AJAX in diesen Bearbeitungsformularen für Panel-Inhaltstypen zu verwenden.

Update: Es scheint, dass Sie mit #attached auch nichts anfangen können.

$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
quelle
Als Drupal-Entwickler vom Typ "Panels für alles" kann ich mir vorstellen, dass ich auch in Zukunft eine Verwendung dafür finden könnte. Deshalb habe ich ein Kopfgeld hinzugefügt, um zu sehen, was passiert.
Letharion
Wow, dieses Kopfgeld kam und ging ohne einen Kommentar (Danke übrigens, Letharion). Ist das, was ich verlange, unmöglich oder so?
Aendrew
Sollte erwähnenswert sein, dass ich Javascript erfolgreich mit ctools_add_js();oder drupal_add_js();am Ende von hinzufügen konnte hook_content_type_edit_form();. Wenn Sie nur einfache Dinge im Zusammenhang mit der Benutzeroberfläche tun, scheint dies der beste Anruf zu sein (zumindest bis jemand diese Frage richtig beantwortet).
Aendrew

Antworten:

8

Kurze Antwort: Sie sollten #ajax ['path'] verwenden.

Lange Antwort:

Ein Ajax-Rückruf hilft nicht, da ctools seine Formen anders erstellt. Der von system / ajax durchgeführte Rückruf kann die vollständige Formulardefinition nicht finden und kann daher kein Element finden, für das die Ajax-Anforderung verarbeitet werden soll. Die Verwendung von #ajax [Pfad] löst nur einen Menüpunkt aus.

Sie können dies selbst überprüfen, indem Sie das Formular bei Verwendung von #ajax [Rückruf] ausgeben.

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

Ich habe die simplecontext_content_type_edit_form geändert, indem ich das Widget für die automatische Vervollständigung des Benutzers und Ihr Feld hinzugefügt habe, die beide funktionieren :)

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')),
  );
...

Da Sie jetzt den #ajax-Pfad verwenden, müssen Sie einen Menüpunkt hinzufügen, wie es mir gefallen hat

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

Ein kleiner Tipp zu #attached [js]: Die Inline-js sollten key => value like:

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

Ich habe Firebug verwendet, um den resultierenden Wert und nicht den resultierenden Effekt zu überprüfen. Ich hoffe, dies hilft, Ihr Problem zu beheben.

Clemens Tolboom
quelle
Beeindruckend. Ich bin so begeistert, endlich eine Antwort auf diese Frage zu haben. Werde es gleich ausprobieren. Vielen Dank auch für den Hinweis zum #attached Bit, das war eigentlich das, was ich ursprünglich hatte (aber es wurde geändert, weil ich dachte, dass das nicht richtig sein könnte).
Aendrew
Also irgendein Erfolg? Wäre interessant zu wissen, bevor das Kopfgeld vorbei ist :)
Letharion
Ich hoffe, ich bekomme mein Kopfgeld: p
Clemens Tolboom
Entschuldigen Sie die Verzögerung, da ich etwas Zeit habe, um es zum Laufen zu bringen. Wenn ich versuche, das $ form-Array zurückzugeben, wird mir mitgeteilt, dass meine Validierungsfunktion nicht definiert ist. Dies ist der Fall, und wenn ich versuche, es in meinem Modul erneut zu deklarieren (im Gegensatz zur Plugin-Datei vom Inhaltstyp), wird mir mitgeteilt, dass ich es erneut deklariere. Ich vermute, das ist nicht das, was ich tun muss, aber ich kann nicht herausfinden, wie drupal_json_output strukturiert werden soll, damit etwas ausgegeben wird, das mein Formular als sinnvolle Antwort interpretiert. Irgendeine Hilfe? Ein besseres Beispiel für einen Rückruf würde viel helfen. Vielen Dank!
Aendrew
Ich habe den winzigen Teil Ihrer Frage verpasst, der sich mit dem Rückgabewert befasst: return $ form ['link_target'] ['# default_value']; Dies ist Ihr Versuch, ein Drupal- Formular in einen HTML / Javascript- Kontext zurückzugeben. Das wird nicht funktionieren. Haben Sie ähnliche Dinge in der Benutzeroberfläche des Panels gesehen? (Ich selbst deaktiviere ab und zu JavaScript mit Ansichten Benutzeroberfläche, nur um den nicht js Workflow zu sehen) (diesen Kommentar zig Mal bearbeitet ... umständlich)
Clemens Tolboom
2

Ich hatte ein ähnliches Problem, bei dem ich einen Media-Elementtyp in ein CTools-Inhaltstyp-Plugin aufnehmen wollte, das auch Ajax zur Auswahl eines Bildes verwendet.

Anstelle der Einstellung "Rückruf" wird die eigene Ajax-Einstellung "Pfad" verwendet. Bei der Auswahl eines Bildes wurde das Formular jedoch ohne das Medienelement vollständig neu erstellt.

Ich habe dies darauf zurückgeführt, dass drupal_rebuild_form weder die CTools-Formularumbruchfunktion noch die eigentliche Einstellungsformularfunktion finden konnte. Also habe ich es behoben, indem ich diese Codezeilen zum ctools-Einstellungsformular hinzugefügt habe:

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

}

Vielleicht fehlt mir etwas Offensichtliches, warum die Include-Dateien nicht geladen werden, aber das manuelle Einfügen hat das Problem für mich behoben.

Placinta
quelle
0

Auf meiner Seite musste ich eine Formularumbruchfunktion in die .module-Datei schreiben und den Bereich manuell (wo der ursprüngliche Formularinhalt definiert ist) wie folgt einschließen:

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

Während eines Ajax-Aufrufs kann Drupal jetzt mein Formular abrufen, damit ich die Standard-AJAX-Formular-API verwenden kann.

Pierco
quelle