Formularbeschreibung nach fehlgeschlagener Validierung ausblenden
Eingetragen von rubens (4)
am 28.01.2011 - 13:58 Uhr in
am 28.01.2011 - 13:58 Uhr in
Hallo,
ich habe, wie im Drupalbuch beschrieben ein einfaches Formular erstellt. Bei function formexample_page gebe ich Text aus der über dem Formular steht. Wenn das Formular nach dem absenden die Validierung nicht besteht soll der Text nicht mehr erscheinen. Leider bekomme ich dies nicht hin. Für Lösungen wäre ich sehr dankbar.
<?php
/**
* Implementation of hook_menu().
*/
function formexample_menu() {
$items['formexample'] = array(
'title' => 'Viev the form',
'page callback' => 'formexample_page',
'access arguments' => array('access content'),
);
return $items;
}
/**
* Menücallback, wird aufgerufen wenn der Benutzer http:// beispiel.de/?q=formexample aufsucht.
*/
function formexample_page() {
$output = t('Hier steht der Text der nach fehlgeschlagener Validierung nicht mehr erscheinen soll');
$output .= drupal_get_form('formexample_nameform');
return $output;
}
/**
* Definiert ein Formular.
*/
function formexample_nameform() {
$form['user_name'] = array(
'#title' => t('Your Name'),
'#type' => 'textfield',
'#description' => t('Trag dein Namen ein.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('submit')
);
return $form;
}
/**
* Validiert das Formular.
*/
function formexamplet_nameform_validate($form, &$form_state) {
if (!$form_state['values']['user_name']) {
form_set_error('user_name', t('Du sollst deinen Namen eintragen'));
}
}
/**
* Formularübermittlung nach der Validierung durchführen.
*/
function formexample_nameform_submit($form, &$form_state) {
$name = $form_state ['values']['user_name'];
drupal_set_message(t('Danke %name',
array('%name' => $name)));
}
?>
- Anmelden oder Registrieren um Kommentare zu schreiben
form_set_errors()
am 28.01.2011 - 14:18 Uhr
Man könnte den String bedingt ausgeben, also dann, wenn form_set_errors() nichts zurückgibt.
form_set_errors()
am 28.01.2011 - 16:01 Uhr
Das ist wahrscheinlich eine Möglichkeit oder man prüft ob das Formular bereits gesendet wurde. Aber was ich auch probier, ich bekomme es nicht hin.
Sorry: form_get_errors()
am 28.01.2011 - 23:22 Uhr
<?php
$out = '';
$output .= form_get_errors() ? '' : t('English is default.');
// ...
?>
form_get_errors: stehe immer noch auf dem Schlauch
am 29.01.2011 - 14:14 Uhr
Vielen Dank für deine Hilfe,
die Variante funktioniert auch nicht. Der Text wird immer ausgegeben.
<?php
function formexample_page() {
$out = '';
$output .= form_get_errors() ? '' : t('English is default.');
$output .= drupal_get_form('formexample_nameform');
return $output;
}
?>
Unzufrieden
am 29.01.2011 - 22:06 Uhr
Ich wäre neugierig, wer das eleganter hinkriegt :)
<?php
function formexample_page() {
$output = ($_POST['op'] == 'submit') ? '' : t('English is default.');
$output .= drupal_get_form('formexample_nameform');
return $output;
}
?>
Das gibt die Message nur bei Nichtvalidierung nicht aus.
Gretchenfrage: wie kann man das erfolgreich abgesendete Formular mit gesetzter Erfolgsmessage ohne den vorausgehenden Text anzeigen?
Es gäbe evtl. eine etwas
am 29.01.2011 - 22:01 Uhr
Es gäbe evtl. eine etwas unorthodoxe Lösung:
Man könnte den Text direkt mit in das Formular aufnehmen (als Markup) und dort mit einer Klasse versehen. Wenn dann die Validierung fehlschlägt, bindet man über drupal_add_css eine CSS-Datei ein, in welcher festgelegt wird, dass diese Klasse ausgeblendet werden soll.
<?php
/**
* Implementation of hook_menu().
*/
function formexample_menu() {
$items['formexample'] = array(
'title' => 'Viev the form',
'page callback' => 'formexample_page',
'access arguments' => array('access content'),
);
return $items;
}
/**
* Menücallback, wird aufgerufen wenn der Benutzer http:// beispiel.de/?q=formexample aufsucht.
*/
function formexample_page() {
//Hier kommt nur das Formular, kein extra Text
$output = drupal_get_form('formexample_nameform');
return $output;
}
/**
* Definiert ein Formular.
*/
function formexample_nameform() {
//Hier kommt jetzt dein Text mit rein
$form['text'] = array(
'#type' => 'markup',
'#value' => '<span class="validate-ausblenden">Hier kommt dein Text rein</span>',
);
$form['user_name'] = array(
'#title' => t('Your Name'),
'#type' => 'textfield',
'#description' => t('Trag dein Namen ein.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('submit')
);
return $form;
}
/**
* Validiert das Formular.
*/
function formexample_nameform_validate($form, &$form_state) {
if (!$form_state['values']['user_name']) {
//Hier binden wir nun die extra CSS-Datei ein
$path = drupal_get_path('module', 'formexample');
//CSS-Datei blendet die Klasse "validate-ausblenden" aus
drupal_add_css("$path/css/mein_css.css", 'module');
form_set_error('user_name', t('Du sollst deinen Namen eintragen'));
}
}
/**
* Formularübermittlung nach der Validierung durchführen.
*/
function formexample_nameform_submit($form, &$form_state) {
$name = $form_state ['values']['user_name'];
drupal_set_message(t('Danke %name',
array('%name' => $name)));
}
?>
Und die Datei "mein_css.css" würde dann so aussehen:
.validate-ausblenden {
display: none;
}
Ist zwar etwas ungewöhnlich, klappt aber auf jeden Fall.
Komplizierter, als es auf den ersten Blick aussieht
am 29.01.2011 - 22:24 Uhr
Es gäbe evtl. eine etwas unorthodoxe Lösung
Ja irgendwie ist mir auch aufgefallen, dass das komplizierter ist, als es auf den ersten Blick aussieht.
Bei dieser Lösung stimmt aber für mein Gefühl das Verhältnis von Aufwand mit erwünschter Wirkung nicht mehr so richtig. Zudem ist ja in einem Textbrowser der Text immer noch da. CSS wäre insofern vom Ansatz her eher wie ein Vertuschen des Nichtfunktionierenden.
Aber es ist vernünftig, dass Du den Einführungstext in die Formularverarbeitung mit hineinnimmst, dadurch stimmt dann schon einmal der Kontext, der ja sonst gar nicht mehr gegeben ist. Wie kann ein Absatz wissen, was in einem Formular unter ihm passiert, ohne auf die $GLOBALS zugreifen zu müssen?
Naja, wirklich aufwändig wäre
am 30.01.2011 - 00:02 Uhr
Naja, wirklich aufwändig wäre das nun auch wieder nicht. Und auf Text-Browser nehme ich bei mir z. B. meist kaum Rücksicht, weil dann ohnehin die Seite nicht mehr funktioniert, wie sie soll.
Ich hatte auch mal probiert, in der Validierungs-Funktion einfach den Wert des Markups zu ändern, quasi so:
<?php
function formexample_nameform_validate(&$form, &$form_state) {
if (!$form_state['values']['user_name']) {
$form['text']['#value'] = '';
form_set_error('user_name', t('Du sollst deinen Namen eintragen'));
}
}
?>
Der Wert wird in $form auch geändert (wenn man $form als Referenz übergibt) aber es erscheint trotzdem noch nach der Validierung.
Cache
am 30.01.2011 - 00:24 Uhr
Das Problem ist der Form-Cache, sobald Du den Einleitungstext in das Formular hineinnimmst. Dieser gute Mann geht der Sache nach - aber das kommt mir insgesamt denn doch vor wie mit Kanonen auf Spatzen ....
Also ich würde wirklich auf die Globals zurückgreifen. Alles andere ist ja bei Lektüre des Codes in zwei Jahren (spätestens beim nächsten Drupal-Upgrade) nicht mehr nachvollziehbar. Vor allem darum, weil sich gerade die API's von Version zu Version hübsch entwickeln, und wir haben ja hier gerade eine etwas unhandliche API-Ecke erwischt. Oder Du schreibst einen Roman in die Kommentare.
Was das Verschieben von Funktionalität in den Theming-Layer betrifft, kann ich Dir immer noch nicht aus vollem Herzen zustimmen. Wir sind ja hier in einem Modülchen, dass etwas tun soll, es nun irgendwie nicht schafft und dann zum Themer sagt: "Hey, mach Du das jetzt."
Aber natürlich, in der ganz privaten Praxis führen viele Wege nach Rom.
Gute Nacht!
Zugegeben, da das mit CSS in
am 30.01.2011 - 04:25 Uhr
Zugegeben, da das mit CSS in die Theming-Richtung abgleitet, sollte man es evtl. lieber lassen.
Aber ich habe gerade nochmal nachgeschaut, weil ich beim besten Willen nicht glauben wollte, dass es nicht geht (hatte schon selbst Formulare nach einem Rebuild verändert, allerdings klappt das aus der Validate-Funktion heraus nicht, sondern man muss in die Submit-Funktion auslagern) und ich habe zumindest eine funktionierende Möglichkeit für den Thread-Ersteller gefunden.
Wir benötigen:
- das storage-Array
- die rebuild-Info
Und zwar überprüft man in der Form-Funktion, ob ein bestimmter Wert im storage-Array, nennen wir ihn mal Text-Wert, gesetzt ist. Wenn nicht (was ja beim erst-Aufruf eines Formulars der Fall ist), dann belegen wir ihn mit dem Eingangstext.
Anschließend bekommt das Markup-Element den Text-Wert als #value zugewiesen.
In der Validate-Funktion prüfen wir nun, ob die Validierung klar geht. Wenn es ein Problem gibt (Feld nicht ausgefüllt), dann wird im storage-Array eine entsprechende Information gespeichert. Es wird allerdings kein Fehler mittels form_set_error ausgegeben.
In der Submit-Funktion wird nun geprüft, ob es in der Validate-Funktion einen Fehler gab. Wenn dies der Fall ist, kann man den Text-Wert im storage-Array auf einen leeren String setzen, kann eine entsprechende Nachricht ausgeben und die rebuild-Info auf TRUE setzen. Dann wird das Formular neu erstellt, der Text-Wert ist gesetzt (wird also nicht mit dem Eingangstext belegt) und wird verwendet --> Text ist verschwunden.
Sollte es keinen Fehler geben, kann man die Daten ganz normal verarbeiten.
Das würde z. B. so aussehen:
<?php
/**
* Implementation of hook_menu().
*/
function formexample_menu() {
$items['formexample'] = array(
'title' => 'Viev the form',
'page callback' => 'formexample_page',
'access arguments' => array('access content'),
);
return $items;
}
/**
* Menücallback, wird aufgerufen wenn der Benutzer http:// beispiel.de/?q=formexample aufsucht.
*/
function formexample_page() {
$output = drupal_get_form('formexample_nameform');
return $output;
}
/**
* Definiert ein Formular.
*/
function formexample_nameform() {
//prüfen, ob Text-Wert gesetzt ist
if (!isset($form_state['storage']['text']))
{
//Wenn nicht --> mit Eingangstext belegen
$form_state['storage']['text'] = "Hier kommt noch dein Text rein";
}
//Text-Wert wird als #value verwendet
$text = $form_state['storage']['text'];
$form['test_text'] = array(
'#type' => 'markup',
'#value' => "<span>$text</span>",
);
$form['user_name'] = array(
'#title' => t('Your Name'),
'#type' => 'textfield',
'#description' => t('Trag dein Namen ein.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('submit')
);
return $form;
}
/**
* Validiert das Formular.
*/
function formexamplet_nameform_validate($form, &$form_state) {
if (!$form_state['values']['user_name']) {
//Nur vermerken, dass Validierung fehlgeschlagen ist
$form_state['storage']['validation_failed'] = '1';
//Keine Fehler ausgeben o. Ä.
}
}
/**
* Formularübermittlung nach der Validierung durchführen.
*/
function formexample_nameform_submit($form, &$form_state) {
//Prüfen, ob es einen Fehler gab
if ($form_state['storage']['validation_failed'] == '1')
{
//Wenn ja --> Text-Wert auf leeren String setzen
$form_state['storage']['text'] = '';
//Nachricht ausgeben
drupal_set_message('Du sollst deinen Namen eintragen', 'error');
//Formular neu aufbauen
$form_state['rebuild'] = TRUE;
}
else
{
//Wenn es keinen Fehler gab --> Daten verarbeiten
$name = $form_state ['values']['user_name'];
drupal_set_message(t('Danke %name',
array('%name' => $name)));
}
}
?>
Das funktioniert auf jeden Fall auch und ist meiner Meinung nach nicht sonderlich aufwendig oder kompliziert. Und es wir komplett alles in den Formular-Funktionen abgehandelt und geregelt. Kleiner Nachteil ist, dass man form_set_error nicht verwenden kann, aber das wäre evtl. zu verkraften, wenn man auf das Ausblenden des Textes wert legt.
Es funktioniert :-)
am 30.01.2011 - 14:36 Uhr
Das sind ja interessante Lösungen für die ich mich bedanken möchte. Allerdings ist die von tumblingmug schon die eleganteste. Auch seinen Ausführungen schließe ich mich voll und ganz an. Deshalb noch mal besonderen Dank an ihn.