Listing 2
// Spaltenkonfiguration var myColumnDefs = [ { key:"id", hidden:true }, { key:"surname", label:"Nachname", sortable:true }, { key:"firstname", label:"Vorname", sortable:true }, { key:"street", label:"Straße", sortable:true }, { key:"zip", label:"PLZ", abbr:"Postleitzahl", sortable:true }, { key:"city", label:"Stadt", sortable:true }, { key:"country", label:"Land", sortable:true }, { key:"email", label:"E-Mail", sortable:true, resizeable:true, formatter:"email" }, { key:"color", label:"Farbe", sortable:true }, { key:"amount", label:"Betrag", sortable:false, formatter:"currency" }, { key:"date", label:"Datum", sortable:false, formatter:"date" } ]; // Felddefinitionen für das Responseschema Examples.myFieldDefs = [ { key:"id" }, { key:"surname" }, { key:"firstname" }, { key:"street" }, { key:"zip" }, { key:"city" }, { key:"country" }, { key:"email" }, { key:"color" }, { key:"amount" }, { key:"date", parser:function(date) { if (date == null) return null; var d = date.split("-"); return new Date(d[0], d[1] - 1, d[2]); } } ]; // Konfiguration der Datenquelle für das Grid var myDataSource = new YAHOO.util.LocalDataSource(YAHOO.util.Dom.get("grid")); myDataSource.responseSchema = { fields: myFieldDefs }; // Initialisierung des Grids var myDataTable = new YAHOO.widget.DataTable("markup", myColumnDefs, myDataSource);
Über das DataSource-Objekt (YAHOO.util.LocalDataSource) definieren wir, welche Datenquelle im DataTable verwenden werden soll. Die DataSource-Objekte können direkt instanziiert oder per Factory-Klasse YAHOO.util.DataSource erzeugt werden (Tabelle 1).
Objekt | Datenquelle |
---|---|
YAHOO.util.FunctionDataSource | JavaScript Funktion als Datenquelle |
YAHOO.util.LocalDataSource | Array, JSON, XML, HTML als Datenquelle |
YAHOO.util.ScriptNodeDataSource | Remote-Daten per YUI Get Utility |
YAHOO.util.XHRDataSource | Remote-Daten per YUI Connection Manager Utility |
Die DataSource-Klassen sind so implementiert, dass sie versuchen, den Rückgabetyp der Datenquelle automatisch zu erkennen. Alternativ kann der Rückgabetyp auch direkt per Objektvariable responseType definiert werden: myDataSource.responseType = YAHOO.util.XHRDataSource.TYPE_HTMLTABLE;. Mögliche Rückgabetypen sind Folgende:
- YAHOO.util.DataSource.TYPE_JSARRAY
- YAHOO.util.DataSource.TYPE_JSON
- YAHOO.util.DataSource.TYPE_XML
- YAHOO.util.DataSource.TYPE_TEXT
- YAHOO.util.DataSource.TYPE_HTMLTABLE
Nach der Initialisierung des DataTable erhalten wir ein funktionsfähiges DataGrid, das die auf- und absteigende Sortierung der Daten per Spalte unterstützt.
Abb. 3: Erzeugtes DataGrid (Vergrößern)
Um dem DataGrid eine Pagination-Funktion hinzuzufügen, übergeben wir beim Instanziieren des DataTable als vierten Parameter das Paginator-Objekt:
var myConfig = { paginator: new YAHOO.widget.Paginator({ rowsPerPage: 15 }) };
Das Paginator-Objekt unterstützt automatisch die Sortierfunktion und berücksichtigt diese beim Blättern der Seiten.
Abb. 4: DataGrid mit Paginator (Vergrößern)
DataGrid mit XHRDataSource oder das Arbeiten mit großen Datenmengen
Ein schnell ersichtliches Problem beim Verwenden der Markup-Lösung im Zusammenhang mit großen Datenmengen ist, dass der Browser in einem ersten Schritt alle Daten als HTML-Tabelle rendert und im zweiten Schritt diese per DataTable parst und erneut rendert. Da in jeder Webapplikation die Daten in einer Datenbank vorgehalten werden, können wir uns das zunutze machen, indem wir auf das Rendern der HTML-Tabelle verzichten und die Daten per XMLHttpRequest laden. Dafür müssen wir zuerst im YUI Loader definieren, dass wir zusätzlich die Komponenten YAHOO.util.Connect und YAHOO.lang.JSON benötigen: require: [„yahoo“, „yahoo-dom-event“, „logger“, „datatable“, „connection“, „json“]. Das LocalDataSource-Objekt tauschen wir gegen ein Objekt vom Typ YAHOO.util.XHRDataSource aus und konfigurieren dieses wie folgt:
var myDataSource = new YAHOO.util.XHRDataSource("grid_query_data.php"); myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON; myDataSource.responseSchema = { fields: Examples.myFieldDefs, resultsList: 'results', metaFields: { totalRecords: "totalRecords" } };
Als responseType definieren wir im Response-Schema JSON. Das Response-Schema für Daten in JSON erwartet zwei weitere Parameter, die die zu verwendenden JSON-Variablen im Response definieren:
{ "results" : [ {"id":"47","surname":"Aguilar","firstname":"Hollee", ...}, {"id":"137","surname":"Alvarado","firstname":"Quin","street" ... }, [...] ], "totalRecords" : 80 }
Die Variable results wird in unserem JSON-Response die Daten enthalten und die Variable totalRecords die Gesamtzahl der in der Datenbank vorhandenen Datensätze.
Um auch in der dynamischen Variante nicht auf die Sortierfunktion und den Paginator verzichten zu müssen, definieren wir in unserem Konfigurationsobjekt dynamicData = true und weisen der Objektvariable generateRequest eine Funktion zu, die bei jedem Nachladen von Daten einen Query String mit den benötigten Informationen erstellt:
generateRequest = function(state, table) { var query = '?start=' + state.pagination.recordOffset; query += '&count=' + state.pagination.rowsPerPage; if (state.sortedBy) { query += '&sort=' + state.sortedBy.key; query += '&dir=' + state.sortedBy.dir; } return query; };
Um dem Paginator noch mitzuteilen, dass wir die Gesamtzahl der vorhandenen Datensätze (totalRecords) vom Server beziehen, belegen wir die Objektvariable handleDataReturnPayload mit einer Funktion:
myDataTable.handleDataReturnPayload = function(request, response, payload) { payload.totalRecords = response.meta.totalRecords; return payload; }