Wednesday, April 27th 2011, 8:12pm
Tags
abhängigkeit,
AJAX,
auswahl,
dependency,
Feld,
nachladen,
Select
Abstract
Dieses Tutorial vermittelt die Kenntnisse um beliebig viele Select-Felder mit AJAX zu verbinden.
Article
index.html
|
HTML Code
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" xml:lang="de">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>Select-Auswahl mit AJAX Abhängigkeit</title>
<script type="text/javascript" src="script.js"></script>
<style type="text/css">
<!--
/* demostyle - not necessary to make it work*/
body{font-size:11pt;font-family:Verdana,Arial,Sans}
//-->
</style>
</head>
<body onload="sendRequest(null, 'elem1')">
<form method="post" action="" id="ajaxSelect">
<table>
<tr id="elem1" style="display:none">
<td>HauptKategorie:</td>
<td><select name="hauptkategorie" size="4" onchange="sendRequest(this, 'elem2')"><option value=""></option></select></td>
</tr>
<tr id="elem2" style="display:none">
<td>UnterKategorie:</td>
<td><select name="unterkategorie" size="4" onchange="sendRequest(this, 'elem3')"><option value=""></option></select></td>
</tr>
<tr id="elem3" style="display:none">
<td>UnterUnterKategorie1:</td>
<td><select name="unterunterkategorie" size="4" onchange="sendRequest(this, 'elem4')"><option value=""></option></select></td>
</tr>
<tr id="elem4" style="display:none">
<td>UnterUnterKategorie2:</td>
<td><select name="unterunterkategorie" size="4" onchange="sendRequest(this)"><option value=""></option></select></td>
</tr>
</table>
<div>
<input type="submit" />
</div>
</form>
</body></html>
|
script.js
|
JavaScript Code
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
/**
* clears a select form element
*
* @param targetSel - dom reference to the select element
*/
function clearSelect(targetSel) {
for (var i=targetSel.length; i>=0; i--) {
targetSel.options[i] = null;
}
}
/**
* sends a request under usage of a loading graphic - targettable has to be positioned relative
*
* @param srcref - reference to the select element with chosen data
* @param target - form element name of target element
*/
function sendRequest(domref, target) {
// skip if no target specified
if(!target) return false;
// save reference to next target
if(domref) domref.followup = target;
var req;
try {
req = window.XMLHttpRequest ? new XMLHttpRequest():
new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
// no AJAX Support
}
req.onreadystatechange = function() {
if ((req.readyState == 4) && (req.status == 200)) {
// merge empty line with response
var data = eval('(' + req.responseText + ')');
var targetRef = document.getElementById(target);
var targetSel = targetRef.getElementsByTagName('select')[0];
// make it visible
targetRef.style.display = 'block';
// clear old data
clearSelect(targetSel);
// fill with data from json response
var i=0;
for(var x in data) {
targetSel.options[i++] = new Option(
data[x].text,
data[x].id
);
}
// clear all followups
while(targetSel.followup) {
targetRef = document.getElementById(targetSel.followup);
// make it hidden
targetRef.style.display = 'none';
// mark next select
targetSel = targetRef.getElementsByTagName('select')[0];
// clear old data
clearSelect(targetSel);
}
}
}
req.open('post', 'ajax.php');
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// send empty post with initial load
req.send(domref !== null ? 'id='+domref.value+'&name='+domref.name : '');
return false; // return false to avoid reload/recentering of the page
}
|
ajax.php
Die meisten werden in dem Umgang mit einer Datenbank vertraut sind. Die ajax.php empfängt eine $_REQUEST Variable "id" und muss eine zweidimensionales Array mit den Schlüsseln "id" und "key" zurückgeben. Auf Basis des
PDO Tutorials habe ich folgenden Demo Code erstellt:
|
PHP Quellcode
|
1
2
3
4
5
6
7
8
9
10
11
12
|
<?php
$sql = "SELECT id, text
FROM category
WHERE parentID = :id";
$stmt = MyDB::getInstance()->prepare($sql);
$stmt->execute(array(
':id' => $_REQUEST['id']
));
$return = $stmt->fetchAll();
echo json_encode($return);
?>
|
Für das Demoscript habe ich folgenden Code bereitgestellt:
|
PHP Quellcode
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
<?php
// u can use $_POST['name'] to build your controller depending on the form name
// but in a category tree the name is not important, we just need the parent id
$id = isset($_REQUEST['id']) ? $_REQUEST['id'] : 0;
// (1) example array with four main categories
for($i=0; $i<4; $i++) {
// four subcategories each
for($j=($i*10); $j<($i*10)+3; $j++) {
$idx = $j+1;
$data[$i][$j] = array(
'id' => $idx,
'text' => sprintf('cat %d (parent:%d)', $idx, $i),
);
// with three childs eiter
for($k=($idx*10); $k<($idx*10)+3; $k++) {
$data[$idx][$k] = array(
'id' => $k,
'text' => sprintf('subcat %d (parent:%d)', $k, $idx),
);
}
}
}
// access the childs with its parent index
$return = $data[$id];
echo json_encode($return);
?>
|
Das Beispiel lässt sich um beliebig viele Select-Auswahlfelder erweitern. Ihr müsst der Methode sendRequest als ersten Parameter immer this übergeben und als
zweiten Parameter die ID des Container, der das abhängige Select-Feld enthält.
Am Ende der Kette - wenn also keine abhängigen Felder mehr nachgeladen werden sollen - übergebt ihr einfach gar keinen Parameter.
|
HTML Code
|
1
2
3
4
5
6
7
8
|
<tr id="elem1">
<td>Haupt Kategorie:</td>
<td><select onchange="sendRequest(this, 'elem2')"></select></td>
</tr>
<tr id="elem2">
<td>Unter Kategorie:</td>
<td><select></select></td>
</tr>
|
Im konkreten Beispiel wurde entschieden abhängige Select-Auswahlfelder erst anzuzeigen, sobald das Elternelement die notwendige Auswahl getroffen hat. Sollte es besser ins Layout passen und ihr wollt stattdessen leere Listenelemente verwendet, so entfernt einfach die style Eigenschaft display:none. Das müsst ihr sowohl im HTML Code machen, als auch alle display Aufrufe im Quelltext entfernen.
Eine Live Demo findet ihr unter
http://demo.easy-coding.de/ajax/select-a…x-abhaengigkeit. Des weiteren wird der kompletten Code hier als ZIP Archiv zur Verfügung gestellt:
download.zip.
Mehr Informationen zum Datenbankbeispiel findet ihr auch hier:
Select-Auswahl mit AJAX Abhängigkeit und verschiedenen Tabellen
Request deletion
report critical content