Formular per AJAX submitten und Error anzeigen bzw. die Änderungen speichern

hallo,

im Titel steht schon alles notwendige, was ich fragen will. und zwar hatte ich die idee das änderungsformular per qtip einzublenden, wenn der user einen beitrag ändern oder hinzufügen will. nun ist es so, dass ich nach dem abschicken keinen reload haben will, sondern die daten per ajax an der server und das resultat entsprechend interpretieren will.

wie gehe ich bei so etwas vor? ich habe noch nicht wirklich viel mit ajax gemacht. vor allem ist es ja so, dass bei einer fehleingabe das formular (also der qtip) ja erweitert wird. und wie soll das laufen, wenn alles okay ist, d.h. bei den eingaben kein fehler aufgetreten ist?

bin echt über jede hilfe froh!

mfg

armin

Dazu musst du dir selbst ein kleines Script basteln. Mit jquery geht sowas ja recht einfach. Der Schlüssel zum Erfolg war hier für mich, bei AJAX-Requests nicht HTML zurückzuliefern (damit müsst ich ja schon wissen, was ich damit machen soll, bevor ich den Request losschicke), sondern ein Schnipsel Javascript, das ausgeführt werden soll. In diesem Schnipsel kann man dann alles mögliche machen: Fehler-Divs einblenden/ausblenden, etc.

Mit jquery.getScript() geht das sehr elegant.

könntest du mir bei der implementierung evtl. etwas behilflich sein? ich weiß leider nicht genau, was ich da alles machen muss =( wäre dir echt sehr dankbar!

Naja, ich kann zwar nicht deine Job machen, aber hier mal eine abgespeckte Basisimplementierung. ;)

Das sollte dich eigentlich in die Gänge bringen. Du wirst aber nicht drum herum kommen, dich etwas mit jquery zu befassen. In diesem Fall verwend ich direkt die jquery.ajax() Methode, damit die POST-Daten mitgeschickt werden.

Zunächst der Controller:


<?php

class AjaxController extends CController {


    public function actionEdit()

    {

        $model=new persons;

        $this->render('edit',array(

            'model' => $model,

        ));

    }


    public function actionSave()

    {

        if (!isset($_POST['persons']))

            return;


        $model=new persons($_POST['persons']);

        if ($model->save()) {

            echo $this->escapeJs("alert('Gespeichert!')");

        } else {

            foreach ($model->getErrors() as $err)

                $txt.=$err[0]."\n";

            echo "alert('".$this->escapeJs("Fehler: \n".$txt)."');";

        }

    }


    // Wird benötigt, da strings im JS-Quellcode keine Zeilenumbrüche haben dürfen

    public function escapeJs($value)

    {

        return addslashes(trim(strtr($value,array("\r\n"=>' ', "\n\r"=>' ', "\n"=>' ',"\r"=>' '))));

    }

}

Und im View:


<?php 

$cs=Yii::app()->clientScript;

$ajaxSaveUrl=$this->createAbsoluteUrl('ajax/save');


$cs->registerCoreScript('jquery');

$cs->registerScript('initButton', <<<EOD

    $('#saveButton').click( function() {

        $.ajax({

            type: 'POST',

            data: $(this).parents('form').serialize(),

            cache: false,

            url: '$ajaxSaveUrl',

            dataType: 'script'  

        });

        return false;

    });

EOD

,CClientScript::POS_READY);

?>

<div class="yiiForm">


<?php echo CHtml::beginForm(); ?>


<div class="simple">

<?php echo CHtml::activeLabelEx($model,'name'); ?>

<?php echo CHtml::activeTextField($model,'name'); ?>

</div>

<div class="simple">

<?php echo CHtml::activeLabelEx($model,'email'); ?>

<?php echo CHtml::activeTextField($model,'email'); ?>

</div>


<div class="action">

<?php echo CHtml::submitButton('Speichern', array('id'=>'saveButton')); ?>

</div>


<?php echo CHtml::endForm(); ?>


</div>

Statt der echo statements in der Save-Action könntest du auch ein View-File rendern, das reinen Javascript code ausgibt. Dort kann man dann auch kompliziertere Javascripts ablegen. So hab ich das bei z.B. bei Stay gemacht.

Hoffe, das gibt dir mal ein paar Ideen…

danke dir! das ist echt klasse. ich muss mich da aber nun erst mal reinarbeiten, da ich das ganz auch etwas anders vor hatte. nur hast du mich auf eine recht gute idee gebracht.

meine idee bisher:

  • user geht auf eine seite

  • klickt auf "beitrag ändern" oder "beitrag hinzufügen"

  • es öffnet sich ein qtip, über den er den beitrag bearbeiten kann

  • nach dem abschicken wird der beitrag per ajax an den server geschickt, geprüft, ob alles passt

  • wenn nein, dann werden live die fehler angezeigt (das wird so naja…)

  • wenn alles passt, dann reload der seite und sprung zum beitrag (per anker).

die neue idee wäre es, gleich live den beitrag einzublenden, also komplett ohne reload zu arbeiten. dafür habe ich aber bisher zu wenig mit ajax und javascript gemacht. daher wird das wohl einiges an zeit kosten, wie ich finde… nun ja, schauen wir einfach mal =)

danke dir jedenfalls nochmals!

Bist du eigentlich sicher, dass es ein submitButton ist? Ich würde sagen, dass es doch ein normaler Button sein muss, oder? Denn sonst wird die Seite ja neu geladen und nicht auf das Ergebnis gewartet!

Jo, bin ich :)

Durch das return false; wird die default-action des buttons unterbunden. Auf diese Weise kann man sehr schön auch ne Fallback-Strategie aufbauen, falls jemand js deaktiviert hat… aber dazu müsste natürlich die edit action etwas angepasst werden …

hallo

vielen dank für deine infos. ich versuche seit tagen, so etwas zu entwickeln. :wink:

  1. wenn ich deinen code bei mir ausführe, kriege ich folgende fehlermeldung:

missing ; before statement

  1. anstelle eines alert würde ich gerne die einzelnen fehlermeldungen unterhalb des textfeldes anzeigen, sofern die validierung scheitert. wie stelle ich das am einfachsten an.

any help very welcome!

cheerio.f

Hi,

@Mike

Das halte ich jetzt einfach mal für ein Grücht, das Strings in JS keine Zeilenumbrüche enthalten dürfen.

Könntest du etwas genauer auf deine Motivation für diese Annahme eingehen?

@fabooo

Er zeigt dir doch die Zeilennummern an, in der ihm ein Semikolon fehlt. Schau einfach dort und ergänze es :wink:

Ist es möglicherweise ein fehlendes Semikolon beim abschließenden Heredoc-Tag ‘EOD’ im View?

Du kannst statt einen JS-Script einfach ein Array z.B. im JSON Format bei deiner Action zurückgeben. Im AJAX-Aufruf gibst du eine Callback-Funktion als Option ‘success’ an, die muss dann die Fehlermeldungen in die Seite einbetten.

Na gut, ich stelle gerade fest, dass man mit dieser Aussage vermutlich nicht viel anfangen kann, wenn man so gar nicht in der Materie drin ist - sorry.

Wenn ich dazu komme, dann schreib ich gleich ein kurzes Beispiel.

Gruß

Sorry, war etwas ungenau formuliert. Was ich meinte, war, dass sowas in js nicht erlaubt ist:


var x="Ein text

  über mehrere Zeilen";



Deshalb müssen in der Antwort alle HTML-Texte, die z.B. an eine jquery Funktion übergeben werden vorher von Zeilenumbrüchen bereinigt werden.