Ajax in einer TemplateEngine

gibt es einen einfachen weg, bzw. überhaupt eine weg ein AJax Request und Response Objekt in eine Template Engine zu integrieren.

Momentan holt sich mein command das komplette template und schickt das geränderte an das Repsonse objekt.
Mit Ajax will ich aber nur die Änderung abschicken!? Nur wie???

Hat jemand Rat?

Greetz
 
Ich versteh Dein Problem nicht ganz, Du kannst ja einfach in Deinem Template einen Ajax-Request, welcher durch einen Event oder so ausgelöst wurde, abschicken z.B. an GetTable.php und verarbeitest dann einfach den Response im Template. Wo liegt das Problem?
 
Wenn ich dich richtig verstanden habe, dann ist deine Ansicht richtig.
Aber:
Über den FrontController wird das richtige command geladen und das entsprechende Template über die Template Engine.
Momentan habe ich das auch so, sprich das Ajax Request im Template drinn und eine separate *.php Datei die das Request bearbeitet.
Aber wiederspricht das nicht dem Aufbau des zugehörigen Command? Denn eigentlich ist ja mein Command für die Verarbeitung und die Weiterleitung an die entsprechende Klasse für das Ajax Request zuständig, oder?
 
Ok, da Du anscheinend MVC benutzt stellt das ganze auch kein Problem dar. Ich gehe mal davon aus, dass Du in Deinem Command (Controller) Dein Template z.B. in einer run-Methode initialisierst und aufrufst. Wenn Du dann an den Controller ein Request-Objekt übergibst oder Zugriff auf das Request-Objekt hast, dann könntest Du das ganze z.B. so lösen:

PHP:
class MyCommand extends Command {
    
    //Die Methode, die der FrontController aufruft, in diesem Beispiel die run()-Methode
    public function run(Request $request) {
        if ($request->exists('ajaxRequest')) {
            //Führe Code aus
            echo json_encode($response);
            return;
        }
        $template->display('MyTemplate.tpl.php');
    }

}

So durchläuft der Request den normalen Workflow. Das ganze ist natürlich nur ein Beispiel, da ich nicht weiss wie Dein FrontController sprich Framework arbeitet. Natürlich könntest Du auch einen eigenen Command (Controller) für diese Ajax-Requests erstellen.
 
Bin noch nicht ganz bei Dir!

Also in meinen FrontController läuft ja "eigentlich" das ganze ab.

Das Request und Response Object wird an mein Command gereicht. hier prüfe ich welche Aktion übergegebn wurde und ruf edie entsprechende Methode auf. In der Methode z.B. SortAktion initialisiere ich die DB und suche mir die gewünschte Daten. Nun hole ich mir mein Template und schreibe die Daten in die Platzhalter und übergebe das ganze dann im anschluss an mein responseobject und render das ganze
PHP:
$this->response->write( $this->render() );
 $this->reset();
wenn ich jetzt aber nur einen teilbereich ändern möchte, was mir ajax ermöglicht, will ich jetzt nicht mehr dass ganze neu render und komplett an den Browser senden, sondern nur die Änderung ??? Das habe ich noch nicht ganz verstanden. Zur Info: Im Prinzip habe ich das Buch DesignPattern angewendet und meinen Bedürfnissen angepasst...
 
Ok, nochmal ein Beispiel auf Basis Deiner Informationen über Dein Command:

PHP:
class MyCommand extends Command {
    
    private $response;
    private $request;
    
    public function __construct(Request $request, Response $response) {
        //Natürlich könntest Du noch auf einen speziellen Ajax-Parameter oder so prüfen.
        switch ($request->get('action')) {
            //Deine Ajax-Action
            case 'sortAction':
                $this->sortAction();
                break;
            default:
                $this->defaultAction();
        }
    }
    
    /**
     * Stellt einfach mal Deinen normalen Ablauf dar.
     */
    private function defaultAction() {
        $this->response->write($this->render());
        $this->reset();
    }
    
    /**
     * Deine Ajax-Action, die auf den Ajax-Request reagiert und die Daten zurück schickt.
     */
    private function sortAction() {
        //Daten aus der DB laden usw.
        //Hier gibst Du einen json-String mit Deinen Daten an Deinen XMLHttpRequest zurück.
        echo json_encode($data);
        return;
    }
    
    /**
     * Hier wird ja wahrscheinlich Dein Template initialisiert und gerendert.
     */
    private function render() {
        
    }
    
    private function reset() {
    
    }
}

Ich hoffe, dass ich so annähernd ein Command von Dir hinbekommen habe. Wie Du jetzt sehen kannst musst Du einfach nur die Daten per echo zurück schicken. Du brauchst ja dem Fall kein Template usw., nur Daten holen verarbeiten und zurück an den Browser schicken, mehr ist das nicht.
 
Hast du super hinbekommen... :wink:

ich danke Dir sowiet, denn jetzt habe ich es verstanden... denk ich..

mein Problem war das
PHP:
  echo json_encode($data);
        return;
werden das ganze dann heute abend nochmal umsetzen

Danke für Deine Mühe
 
So ein Mist, habe doch noch ne Frage.

meine Command(nur die eine methode)

PHP:
protected function SortAktion( $message = '', $error = '') {
        $this->db->setTable( 'kunde' );
        $this->db->initConnection();
        $result = $this->db->like( $this->request->getParameter( 'str' ) );
         
         $string = '';
         foreach ($result as $row) {
             $string .= "<tr onmouseover=\"changeClass(this,'hover')\"
            onmouseout=\"changeClass(this,'normal')\"
            onclick=\"setHeaderInformation(" . $row["id"] . ");\">
            <td>" . $row["id"] . "</td>
            <td>" . $row["vorname"] . ' '. $row['nachname'] . "</td>
            <td>" . $row["strasse"] . ' ' . $row["haus_nr"] . "</td>
            <td>" . $row["plz"] . ' ' . $row['ort'] . "</td>
            <td>" . $row["telefon"] . "</td>
            <td>" . $row["handy"] . "</td>
            </tr>";                
        }

        $this->response->setUpdate();
        $this->response->write( $string );
    }
Mein Response teil für die Ausgabe
PHP:
    public function flush() {
        if ( $this->update === false ) {
            header( "HTTP/1.0 {$this->status}" );
            foreach ( $this->headers as $name => $value ) {
                header ( "{$name}: {$value}" );
            }
            print $this->body;
        }
        else {
            header('Content-Type: application/json');
            echo json_encode( $this->body );
        }
        $this->resetParas();
    }
mein frontcontroller teil
PHP:
    public function handleRequest( Request $request, Response $response ) {
        $reg = Registry::getInstance();
        $reg->setRequest( $request );
        $reg->setResponse( $response );
        $command = $this->resolver->getCommand( $request );
        $command->execute( $request, $response );
        $response->flush();
    }
So nun mein "Denkfehler" / Problem:

ich bekommen die Daten bis zu Sortmethode übergeben, und gehändelt. Ich habe immer noch ein Problem nur den zu aktualisierenden Bereich im Browser darzustellen. WO ist mein Fehler? Sieht jemand mehr durhc als ich? Habe wahrscheinlich in meinem Geistigen Wirrwar, noch mehr geistige fehleistungen reinprogrammiert???? X(
 
Was genau macht er, oder was macht er nicht?

Ist $this->update in Deiner Response-Klasse auf True? Kommst Du in der Flush-Methode in den Else-Teil?

Welche Daten möchtest Du als json-String Enkodieren? Diese Tabellen-Rows in der SortAktion-Methode? Wenn ja, wäre das keine saubere Lösung. Ein Json-String ist eigentlich mehr für Arrays sprich für eine Menge von Daten gedacht.
 
ok, vielleicht beschreibe ich das problem etwas genauer (asche über mein haupt).

Muss hier auch dazu sagen das Ajax fü mich komplett neu ist! Obwohl Ajax ja eigentlich kein Hexenwerk ist biege ich hier ("hoffe ich") nur falsch ab !?

Also:
Ja, $this->update ist auf true
Ja, ich komme in den else zweig.
Ja, ich möcht die Tabellendaten damit enkodieren !? Oder nicht !?

Ich habe eine Tabelle mit Daten (Beispiel Kundendaten). Hier können x beliebig viele Daten drinne stehen. Nun setze ich ein Textfeld ein und übergebe einer Javascript Function den Parameter ( onkeyup="search(this);" ), um die Daten in der Tabelle nach den übereinstimmungen aufzulisten

var xmlhttp;
function showUser(str)
{
alert(str);
xmlhttp=GetXmlHttpObject();
if (xmlhttp==null) {
alert ("Browser does not support HTTP Request");
return;
}

//var url ="index.php";
//var params = "command=default&aktion=sort";
xmlhttp.onreadystatechange=stateChanged;

xmlhttp.open("GET", "index.php?command=default&aktion=sort&str="+str+"&sid="+Math.random(), true);
xmlhttp.send();
}
function stateChanged()
{
if (xmlhttp.readyState==4)
{
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
}
}
function GetXmlHttpObject()
{
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
return new XMLHttpRequest();
}
if (window.ActiveXObject) {
// code for IE6, IE5
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}

Soweit ( wenn es denn auch so der richtige Weg ist ?? ) funktioniert das.
Sprich die Sort Methode wird aufgerufen und ich kann auf den Request zugreifen.
ich hole mir jetzt die Daten aus der DB select * from ....... like 'a%' usw.
und möchte diese zurückgeben und auch nur in derc Tabelle aktualisieren.

Ich weis auch an dieser stelle nicht ob das der absolute performance schonende weg ist, da ich ja jedes mal die übereinstimmungen aus der DB hole und mir auch die Daten jedesmal anzeigen lassen will.

Mein Problem liegt jetzt darin dem AjaxResponse die zur Anzeige zu bringenden Daten zu returnen. Ich bekomme auf meinen Weg immer ein "Null" dargestellt im Browser.
Der Frontcontroller ruft am Ende dann im meinen ResponseObject die flush() Methode auf um die Daten dann halt darzustellen. die Update IEgenschaft setze ich mir nur damit ich weis das es eine "Ajax" anfrage ist. Mmmh je mehr ich darüber nachdenke .... Grübel... Muss ich die Daten nicht auch an die JS Funktion übergeben, da ich ja auch mit dieser das Ajax Request abgesendet habe...
Naja,
hier liegt nun mein Problem... Ich hoffe man konnte das eher verstehen?

Ich versuche mich halt damit zu beschäftigen um auch damit besser umgehen zu können und auch diese in meine MVC sinnvoll und auch Wichtig: RICHTIG einzusetzen...
 
Falls Du Firebug hast, könntest Du gucken was genau im Response steht. Aber ich tippe mal auf json_encode(), lass das ganze einfach mal weg und gib denn String nur mit dem echo aus. json_encode hat nämlich ein Problem mit Sonderzeichen.
Um auf den Response zugreifen zu können gibt es zwei Möglichkeiten, einmal mit responseText und einmal mit responseXml. Du selbst benutzt ja die responseText, was in Deinem fall absolut korrekt ist.

Sollte das nichts bringen, so müsstest das ganze wirklich mit Firebug debuggen.

Ach ja, ich würde auf jedenfall erst ab dem 3. oder 4. Zeichen einen Request abschicken und wenn eine bestimmte Zeit zwischen zwei keydown-Events verstrichen ist. Somit wird nicht so viel Last und Traffic erzeugt.
 
Danke für Deine Unterstützung.
Habe gerade die Ausgabe auf den Browser bekommen, mit der Ausnahme das der Tag so dargestellt wird --> ?td/>
Somit sollte das eine Problem gelöst sein... Danke...

Hättest Du bei dem Umlaut noch Rat?
 
Jage mal die Daten durch die utf8_encode-Function bevor Du Sie an den Browser zur Ausgabe schickst. Deine Seite muss dann natürlich als UTF-8 ausgeliefert werden.

Schickst Du die Daten jetzt mit echo oder noch mit json_encode an den Browser?
 
ich sende die Daten wie du vorgeschlagen hast:
PHP:
    header('Content-Type: application/json');
            echo $this->body;
Meine eigentlich das ich das auch vorher schon so versucht hatte !? Denke aber in meinem Wirrwarr habe ich was übersehen, denke es ist noch ein return oder irgendetwas anderes auf der strecke geblieben.

Deine Seite muss dann natürlich als UTF-8 ausgeliefert werden.
:rolleyes: Ooops... ein wenig peinlich ...
 
Gehts jetzt, oder funktioniert noch was nicht?


Also denn Content-Type würde ich auf text/html ändern, da json ja jetzt nicht mehr korrekt ist.

Deine Seite muss natürlich nur UTF-8 ausgeliefert werden, wenn Deine Daten auch als UTF-8 vorliegen.

Denke aber in meinem Wirrwarr habe ich was übersehen, denke es ist noch ein return oder irgendetwas anderes auf der strecke geblieben.

Sowas passiert mir auch häufiger, dass ich ein return oder so vergessen, und dann mehr Daten zurück bekomme als mir lieb sind.
 
Funktioniert und die Daten werden aktualisisert.
Meine Tabellendaten werden gesetzt und dargestellt.

kleine Frage noch:
Ich handle das ganze jetzt Asyncron und warte nicht auf den Request.
Da ich aber folge functionen in Javascript aufrufe, greifen diese auf eine nicht
initialisierte Tabelle (DOM) zu.
Jetzt möchte ich das ganze syncron machen und auf ein ergebnis warten.
Dazu setze ich meine .open('','', false); auf false, und da ich mit GET arbeite brauche ich ja auch .send nix mitgegeben. funtioniert aber trotzdem nicht.

Habe hier ein Beispiel was ich anpassen wollte und dem ganzen sehr nahe kommt, welches aber nicht läuft...
Sieht Du, jemand den Grund dafür?
<html>
<head>
<script type="text/javascript">
function showHint(str)
{
if (str.length==0)
{
document.getElementById("txtHint").innerHTML="";
return;
}
var url="gethint.php";
url=url+"?q="+str;
url=url+"&sid="+Math.random();

if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET",url,false);
xmlhttp.send();
}
</script>
</head
<body>

<p><b>Start typing a name in the input field below:</b></p>
<form>
First name: <input type="text" onkeyup="showHint(this.value)" size="20" />
</form>
<p>Suggestions: <span id="txtHint"></span></p>

</body>
</html>

<?php
// Fill up array with names
$a[]="Anna";
$a[]="Brittany";
$a[]="Cinderella";
$a[]="Diana";
$a[]="Eva";
$a[]="Fiona";
$a[]="Gunda";
$a[]="Hege";
$a[]="Inga";
$a[]="Johanna";
$a[]="Kitty";
$a[]="Linda";
$a[]="Nina";
$a[]="Ophelia";
$a[]="Petunia";
$a[]="Amanda";
$a[]="Raquel";
$a[]="Cindy";
$a[]="Doris";
$a[]="Eve";
$a[]="Evita";
$a[]="Sunniva";
$a[]="Tove";
$a[]="Unni";
$a[]="Violet";
$a[]="Liza";
$a[]="Elizabeth";
$a[]="Ellen";
$a[]="Wenche";
$a[]="Vicky";

//get the q parameter from URL
$q=$_GET["q"];

//lookup all hints from array if length of q>0
if (strlen($q) > 0)
{
$hint="";
for($i=0; $i<count($a); $i++)
{
if (strtolower($q)==strtolower(substr($a[$i],0,strlen($q))))
{
if ($hint=="")
{
$hint=$a[$i];
}
else
{
$hint=$hint." , ".$a[$i];
}
}
}
}

// Set output to "no suggestion" if no hint were found
// or to the correct values
if ($hint == "")
{
$response="no suggestion";
}
else
{
$response=$hint;
}

//output the response
echo $response;
?>

habe mir auch nochmal das Tut von
http://www.w3schools.com/ajax/
zu gemüte geführt....
 
Zuletzt bearbeitet:
Du weisst aber schon was der Unterschied zwischen einem asynchronen- und einem synchron-Request ist oder?

Jedenfalls kannst Du bei einem synchronen-Request den onreadystatechange Event nicht mehr benutzen, da Dein Skript solange blockiert wird, bis die vollständige Antwort(Response) vom Server da ist. Was ja eigentlich nicht Sinn und Zweck eines Ajax-Requests ist.

Ich handle das ganze jetzt Asyncron und warte nicht auf den Request.
Da ich aber folge functionen in Javascript aufrufe, greifen diese auf eine nicht
initialisierte Tabelle (DOM) zu.

Welche Javascript-Funktionen greifen auf welche Tabelle zu?

Falls Du aber mit synchronen-Request arbeiten willst, warum auch immer :rolleyes:, hier der angepasst JS-Code wie es geht.

HTML:
<html>
<head>
<script type="text/javascript">
function handleResponse(response) {
 document.getElementById("txtHint").innerHTML = response;
}

function showHint(str) {
    if (str.length==0) {
        document.getElementById("txtHint").innerHTML="";
        return;
    }
    var url="gethint.php";
    url=url+"?q="+str;
    url=url+"&sid="+Math.random();

    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    
    xmlhttp.open("GET",url, false);
    xmlhttp.send();    
    handleResponse(xmlhttp.responseText);
}
</script>
</head
<body>

<p><b>Start typing a name in the input field below:</b></p>
<form>
First name: <input type="text" onkeyup="showHint(this.value)" size="20" />
</form>
<p>Suggestions: <span id="txtHint"></span></p>

</body>
</html>
 
Zurück
Oben