Neues Feld mit hook_form_alter. Wo sind die Daten nach 'Preview'?
am 04.12.2009 - 10:35 Uhr in
Hallo ihr da draußen. Ich bin gerade dabei meine ersten Erfahrungen mit der Modulentwicklung unter drupal zu machen. Mein eigentliches Ziel ist es der forum_node_form
ein neues Textfeld für ein Datum hinzuzufügen. Das habe ich dann auch relativ leicht geschaft, nun besteht jedoch das Problem, dass das Eingabefeld nach der Vorschau leer ist. Also den vom Benutzer eingegebenen Wert vergisst.
Wenn ich während der validate-Phase mit form_set_error()
einen Fehler setze bleibt der Inhalt erhalten. Nur wenn die Daten die Validierung passieren vergisst er sie. Was mache ich falsch?
Ich hab mal den Code eingedampft und ein minimales Modul erstellt welches das Problem ebenfalls zeigt. (Angepasst von: http://www.drupalcenter.de/node/16058 )
<?php
function meinmodul_form_alter(&$form, $form_state, $form_id) {
//if ($form_id == 'forum_node_form') {
$form['extra_feld'] = array(
'#type' => 'textfield',
'#title' => t('Extra'),
//'#default_value' => t('Additional info'),
);
$form['#validate'][] = 'meinmodul_validate_handler';
$form['#submit'][] = 'meinmodul_submit_handler';
//}
}
function meinmodul_validate_handler($form, &$form_state) {
//if ($form['form_id'] == 'forum_node_form') {
//print_r($form_state);
if (strlen($form_state['values']['extra_feld']) < 3) {
form_set_error('extra_feld', t('You have to enter at least 3 characters.'));
}
// }
}
function meinmodul_submit($form, &$form_state) {
// Werte aus $form_state irgendwo speichern
}
?>
- Anmelden oder Registrieren um Kommentare zu schreiben
Sieh Dir doch mal im
am 04.12.2009 - 11:06 Uhr
Sieh Dir doch mal im Originalmodul die Form an. Die Forms-API von Drupal hat viele Möglichkeiten, z.B das setzten eines Default-Wertes. Wenn Du nichts in ein Feld hineinschreibst, wird in der Form auch nichts angezeigt.
Beste Grüße
Werner
Ja das mit dem default-Wert
am 04.12.2009 - 11:18 Uhr
Ja das mit dem default-Wert ist mir klar. Mir geht es darum, dass wenn ich per Hand in das von der forms-api generierte Feld etwas eintrage, die Daten nach einem 'preview/validate' verloren gehen. Also das Feld wieder leer ist.
Alle anderen Felder, also Betreff, Text, usw. behalten nach einer Vorschau die vom Benutzer eingegebenen Werte.
Hast Du denn den Node um
am 04.12.2009 - 11:30 Uhr
Hast Du denn den Node um Dein zusätzliches Feld erweitert? Nur ein Feld in der Form eintragen sorgt ja noch nicht dafür, daß es gespeichert wird. Eine Form holt die Daten nur ab. Anschließend wird z.B. beim Node im Node-Modul die Funktion node_save aufgerufen, aber die sichert natürlich nur, was in der Node-Typ Definition vorhanden ist. Wenn Du den Node-Typ in der Typ-Definition um ein Feld erweiterst, wird das von selbst angezeigt und Du brauchst auch nicht mehr zu zaubern.
Beste Grüße
Werner
Die Parameter, die in der
am 04.12.2009 - 11:39 Uhr
Die Parameter, die in der Dokumentation zu
hook_form_alter
angegeben werden, sind die Parameter, die immer an deine Funktion übergeben werden.Abhängig von dem konkreten Formular, das geändert werden soll, werden noch weitere Argumente übergeben. Bei Node-Formularen ist das z.B. ein Node-Objekt. Auf zusätzliche Argumente kannst du mit
func_get_args
zugreifen. In dem Node-Objekt steht dann das Datum, das du vorher eingegeben hast. Diesen Wert musst du in$form['extra_feld']['#default_value']
eintragen.BTW: Du brauchst keine eigenen Validation- und Submit-Handler implementieren. Du kannst auch einfach warten bis
hook_nodeapi
bei dir vorbeikommt, das passiert automatisch. Diesen Hook musst du sowieso implementieren, da du bei$op = 'load'
dein Datum aus der Datenbank lesen und in den Node eintragen musst. Vielleicht möchtest du auch dein Feld im Node selbst anzeigen; das geht ebenfalls überhook_nodeapi
, nämlich bei$op = 'view'
.--
@wla: Wie kann ich denn die
am 04.12.2009 - 13:19 Uhr
@wla: Wie kann ich denn die Typ-Definition von einem fremden Node-Typ ändern? (Ich will ja mit meinem Modul das node-Formular vom forum.module ändern.)
@traxer: Also rekapitulieren wir (ich habs immernoch nicht geschafft).
Ich bekomme nach http://api.drupal.org/api/function/hook_nodeapi/6 für 'validate' drei Argumente.
0. ein Node-Objekt welches ich verändern kann.
1. Die Operation welche auf das Formular angewendet werden soll.
2. Das Formular welches ich NICHT ändern kann. (Nach api wird ja nur das Objekt als Kopie übergeben, kein Pointer.)
Wenn ich jetzt nun im validate in das Node-Objekt schaue (Argument 0) sehe ich mein Feld mit dem Inhalt ($node->extra_feld->'04.12.2009'). Das dazu gehörige HTML ist leer.
<label for="edit-extra-feld">Datum:</label>
<input type="text" maxlength="10" name="extra_feld" id="edit-extra-feld" size="10" value="" class="form-text" />
Wo soll ich jetzt da
$form['extra_feld']['#default_value']
ändern. Das ist ja nur im Argument 2, und das kann ich nur lesen, nicht ändern.ps: Natürlich hat das Feld in Wirklichkeit einen an mein Modul angepassten Namen, ich verwende hier beim Schreiben nur weiter 'extra_feld' weil das oben so in meinem kleinen Beispielmodul war.
Ich gehe mal davon aus, Du
am 04.12.2009 - 13:49 Uhr
Ich gehe mal davon aus, Du hast CCK schon installiert. Dann kannst Du unter Inhalt > Inhaltstypen > Forumsbeitrag > Felder Verwalten ein weiteres Feld in den Node einfügen.
Beste Grüße
Werner
sr schrieb Wo soll ich
am 04.12.2009 - 14:06 Uhr
Wo soll ich jetzt da
$form['extra_feld']['#default_value']
ändern.Während der Validierung überhaupt nicht. Während der Validierung sorgt Drupal selbst dafür, das das Eingabefeld passend belegt ist. Während der Validierung musst du lediglich prüfen, ob das was im Node-Objekt steht deinen Ansprüchen genügt und falls nicht dann rufst du
<?php
form_set_error('extra_feld', t('The value for the field "extra_feld" is invalid.'));
?>
$form['extra_feld']['#default_value']
musst du inmeinmodul_form_alter
setzten, und zwar anhand des vierten Argumentes, das die Funktion übergeben bekommt.--
Ach CCK. Genau das (und
am 04.12.2009 - 14:09 Uhr
Ach CCK. Genau das (und views) versuche ich gerade aus Geschwindigkeitsgründen loszuwerden. Die cck-Datumsfelder in der mysql-Tabelle sind nur als String gespeichert so das kein ordentlicher Index bei Abfragen genutzt werden kann. Und die Zusammenstellung des Kalenders über views ist zu resourcenintensiv.
Mit dem Modul was ich jetzt schreibe (der Teil der Daten lädt ist schon fertig) konnte ich die Ausführungszeiten im Kalender von ca 120ms auf 50ms senken.
@traxer: In form_alter
am 04.12.2009 - 14:22 Uhr
@traxer:
In
form_alter
bekomme ich nur drei Argumente. Doch im zweiten war was passendes, danke.<?php
function kir_kalender_form_alter(&$form, &$form_state, $form_id) {
switch ($form_id) {
case 'forum_node_form':
$form['extra_feld'] = array(
'#title'=> t('Date'),
'#type' => 'textfield',
'#default_value' => $form_state['node']['extra_feld'],
);
break;
}
}
?>
ABER... in http://api.drupal.org/api/drupal/developer--topics--forms_api.html/6 unter creating forms steht:
Don't use the '#value' attribute for any form elements that can be changed by the user. Use the '#default_value' attribute instead. Don't put values from $form_state['values'] (or $_POST) here! FormsAPI will deal with that for you; only put the original value of the field here.
Ist
$form_state['node']['extra_feld']
ok? Die Daten sehen ja genauso aus wie die unter $form_state['values']['extra_feld'].func_get_args
am 04.12.2009 - 14:38 Uhr
<?php
function kir_kalender_form_alter(&$form, &$form_state, $form_id) {
switch ($form_id) {
case 'forum_node_form':
$args = func_get_args();
$node = $args[3];
$form['extra_feld'] = array(
'#title'=> t('Date'),
'#type' => 'textfield',
'#default_value' => isset($node->extra_feld) ? $node->extra_feld : '',
);
break;
}
}
?>
Falls das nicht funktioniert, dann ist
$form_state['node']['extra_feld']
wohl auch OK.Wenn du dir um Performance sorgen machst, dann wirf mal einen Blick auf
hook_form_FORM_ID_alter
. Dieser Hook hat die gleiche Funktion wiehook_form_alter
, wird aber nur für Formulare mit passender$form_id
ausgeführt (spart also unnötige Funktionsaufrufe und dieswitch
-Anweisung ein).--
Danke funktioniert jetzt
am 04.12.2009 - 15:47 Uhr
Danke funktioniert jetzt alles. Um $node zu bekommen fehlt bei dir ein
$node = $form['#node'];
Gibt es sowas wie
hook_form_FORM_ID_alter
auch fürhook_nodeapi
? Das wird ja auch bei jedem! node-Vorgang ausgeführt und ist ja bei mir eigentlich nur bei einem bestimmten node-type erforderlich.sr schrieb Um $node zu
am 05.12.2009 - 12:45 Uhr
Um $node zu bekommen fehlt bei dir ein
$node = $form['#node'];
Eigentlich ist
$node = $args[3];
dazu gedacht.Gibt es sowas wie
hook_form_FORM_ID_alter
auch fürhook_nodeapi
?Nein. In Drupal 7 werden lediglich die einzelnen Operationen auf eigene Hooks verteilt. Eine Unterscheidung nach Inhaltstypen gibt es auch dort nicht.
--