Yii: CJuiAutoComplete und JSON

Seit Version 1.1.3 gilt CAutoComplete nun als deprecated und es wird zur Nutzung von CJuiAutoComplete, das, wie der Name schon vermuten lässt, auf das jQuery UI-Widget Autocomplete aufsetzt, empfohlen. Bisher lässt die Dokumentation allerdings noch etwas zu wünschen übrig, und möchte man eine hübsche und saubere Ajax-Lösung bauen, ist man dann doch auf die entsprechende jQuery-Doku, das Yii-Forum und Google angewiesen.

Unser Ziel ist also die Verwendung von CJuiAutoComplete via Ajax. Letztlich eigentlich eine ganz einfache Sache.

Der für uns wichtige Teil im View des Formulars sieht wie folgt aus:

<div class="row">
    <?php echo $form->labelEx($model, 'name'); ?>
    <?php 
        $this->widget('zii.widgets.jui.CJuiAutoComplete', array(
            'model'       => $model,
            'attribute'   => 'name',
            'sourceUrl'   => array('person/autoCompleteLookup'),
        ));
    ?>
    <?php echo $form->error($model,'name'); ?>
</div>

Statt ein TextField zu erstellen, laden wir also das CJuiAutoComplete-Widget und geben wie gewohnt als zweiten Parameter ein Array mit entsprechenden Konfigurationanweisungen an.

model bezieht sich logischerweise auf das verwende CModel, und attribute auf die dazugehörige Property. Diese beiden Angaben dienen dem Widget nur zum Generieren des InputFields. Soll sich das Widget auf kein Model beziehen, gibt man statt model und attribute einfach die Option name an. Unspektakulär.

Interessanter ist die Option sourceUrl. Hiermit geben wir die Url, an von der via Ajax Autocomplete-Vorschläge geholt werden sollen. Der Filterbegriff wird in der GET-Variable term mitgesendet und als Response wird ein JSON-Array bestehend aus den Feldern label und/oder value erwartet. Für den Response ist nur jeweils eines der Felder Pflicht. Werden nur value-Felder gesendet dann, werden diese auch als Label genutzt und umgekehrt.

Kommen wir nun zu unserere Action.

public function actionAutoCompleteLookup() 
{
	// Wenn nicht Ajax-Request oder Term fehlt -> 400
	if (!Yii::app()->request->isAjaxRequest || !isset($_GET['term'])) {
		throw new CHttpException(400);
	}
 
	// Models holen
	$c = new CDbCriteria();
	$c->select = 'name';
	$c->limit  = 10;
	$c->compare('name', $_GET['term'], true);
 
	// Models in Array schreiben bzw. fuer CJSON vorbereiten
	$persons = array();
	foreach (Person::model()->findAll($c) as $model) {
		$persons[] = array(
			'value' => $model->id,
			'label' => $model->name
		);
	}
 
	// Das ganze im JSON-Format ausgeben
	echo CJSON::encode($persons);
 
	Yii::app()->end();
}

Wir prüfen den Request erst einmal formal auf Richtigkeit und brechen ggf. mit einem 400er-Statuscode ab, holen dem mitgesendeten Term entsprechend die Models, bereiten diese für die Ausgabe mit Hilfe des Helpers CJSON vor, geben das Ganze dann wie gefordert aus und fertig. Unser Widget läuft!

Dem MVC-Pattern gemäß müssten wir $persons natürlich noch an einen (Partial-)View übergeben und in diesem dann erst CJSON:encode() aufrufen, aber wir wollen es mal nicht übertreiben…

Schlagworte: , , , , , , ,

Kommentieren