YUI AutoComplete with CakePHP
Tuesday, July 29th, 2008YUI Autocomplete
Usually I find the YUI components fairly easy to understand and implement. Not so with Autocomplete. After a lot of aggrivation I have it implemented. Hopefully my work here will save you the same time and hassel I experienced. The resource best resource I found was James Gardner’s YUI Autocomplete AJAX Select Dropdown with ID post.
VIEW:
link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/2.5.2/build/autocomplete/assets/skins/sam/autocomplete.css" script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/yahoo-dom-event/yahoo-dom-event.js" script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/get/get-min.js" script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/connection/connection-min.js" script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/animation/animation-min.js" script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/json/json-min.js" script type="text/javascript" src="http://yui.yahooapis.com/2.5.2/build/autocomplete/autocomplete-min.js"
label for="breed">Breed
input id="breed_id" type="hidden" name="breed_id" />
input id="breed" type="text" name="item" maxlength="50"/>
div id="breedContainer">
script type="text/javascript">
var mySchema = ["ResultSet.Result","Name","ID"];
var myDataSource = new YAHOO.widget.DS_XHR("/find_a_pet/breed", mySchema);
myDataSource.responseType = YAHOO.widget.DS_XHR.TYPE_JSON;
var myAutoComp = new YAHOO.widget.AutoComplete("breed", "breedContainer", myDataSource);
// populate hidden field (id)
function fnCallback(e, args) {
YAHOO.util.Dom.get("breed_id").value = args[2][1];
}
myAutoComp.itemSelectEvent.subscribe(fnCallback);
//myAutoComp.forceSelection = true;
//myAutoComp.useIFrame = true;
CONTROLLER:
// directly execute... /find_a_pet/breed?query=labr
function breed() {
$this->layout = null;
$query = (ctype_print($_GET['query'])) ? $query = $_GET['query'] : $query = '';
//if (!empty($query)) {
$this->set('breed', $this->FindAPet->getBreed($query));
//}
}
MODEL:
public function getBreed($query) {
$sql = "SELECT id, name FROM breed WHERE name LIKE '" . Sanitize::escape($query) . "%' ORDER BY name";
$model = $this->query($sql);
$totalResultsReturned = $this->getAffectedRows(); // do this immediately after the query
$sql = "SELECT COUNT(*) AS count FROM breed";
$result = $this->query($sql);
$totalResultsAvailable = $result[0][0]['count'];
$json = '';
$breed = array();
foreach ($model as $entry) {
$breed['Name'] = $entry['breed']['name'];
$breed['ID'] = $entry['breed']['id'];
$json .= json_encode($breed) . ",";
}
$json = substr($json, 0, strlen($json)-1);
$json = '{"ResultSet": {"totalResultsAvailable":"' . $totalResultsAvailable . '","totalResultsReturned":' . $totalResultsReturned . ',"firstResultPosition":1,"Result": [' . $json . ']}}';
return $json;
}
Missing data in beforeValidate()
If you are submitting a form and the data is not visible in model::beforevalidate(), then you can solve this by adding $this->Model->data = $this->data in the controller before validates(). Once you do this you can use $this->data in beforevalidate().
function admin_add() {
if (!empty($this->data)) {
$this->FindAPet->data = $this->data;
if ($this->FindAPet->validates()) {
$this->FindAPet->save();