IceFaces Tutorial Teil 6 - Sortierbare Tabelle

Veröffentlicht auf von Christopher Olbertz

Was fehlt bei unserer Tabelle noch? Es wäre doch schön, wenn man sie sortieren könnte, indem man auf einen Spaltenkopf klickt. Schauen wir uns mal die nächste bookList.jspx an. Ich habe die Paginatoren der Übersichtlichkeit halber entfernt. Sie sollten ja jetzt in der Lage sein, Paginatoren einzufügen, falls das gewünscht wird.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root version="1.2"
  xmlns:jsp="http://java.sun.com/JSP/Page"
   xmlns:f="http://java.sun.com/jsf/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:ice="http://www.icesoft.com/icefaces/component">
<jsp:directive.page contentType="text/html;charset=ISO-8859-1" pageEncoding="ISO-8859-1"/>
<f:view>
  <ice:outputDeclaration doctypeRoot="HTML" doctypePublic="-//W3C//DTD HTML 4.01 Transitional//EN" doctypeSystem="http://www.w3.org/TR/html4/loose.dtd"/>
  <html>
    <head>
     <title><ice:outputText value="MyOpac - Buecherverwaltungssystem" /></title>
    </head>
    <body>

     <ice:form partialSubmit="true" >

        <ice:dataTable id="dataList"
                       border="1"
                       value="#{dataTableBean.bookList}"
                       rows="#{dataTableBean.showRows}"
                       var="row"
                       sortColumn="#{dataTableBean.sortColumn}"
                       sortAscending="#{dataTableBean.ascending}"
>

            <!--  ID -->
            <ice:column>
                  <f:facet name="header">
                    <ice:commandSortHeader columnName="Id" arrow="true" >
                        <ice:outputText value="Id"/>
                    </ice:commandSortHeader>

                </f:facet>
                <ice:outputText value="#{row.bookId}"></ice:outputText>
              </ice:column>

            <!-- Titel -->
            <ice:column>
                  <f:facet name="header">
                    <ice:commandSortHeader columnName="Title" arrow="true" >
                        <ice:outputText value="Titel"/>
                    </ice:commandSortHeader>

                </f:facet>
                <ice:outputText value="#{row.title}"></ice:outputText>
              </ice:column>

            <!--  Autor -->
            <ice:column>
                  <f:facet name="header">
                    <ice:commandSortHeader columnName="Author" arrow="true" >
                        <ice:outputText value="Autor"/>
                    </ice:commandSortHeader>

                </f:facet>
                <ice:outputText value="#{row.author}"></ice:outputText>
              </ice:column>

            <!-- Seitenanzahl -->
            <ice:column>
                  <f:facet name="header">
                    <ice:commandSortHeader columnName="Pages" arrow="true" >
                        <ice:outputText value="Seitenanzahl"/>
                    </ice:commandSortHeader>

                </f:facet>
                <ice:outputText value="#{row.pages}"></ice:outputText>
              </ice:column>
        </ice:dataTable>
        <ice:messages />
     </ice:form>

    </body>
  </html>
</f:view>
</jsp:root>


Die Änderungen habe ich rot markiert. Sie sehen, dass nicht viel hinzugefügt werden muss, um die Tabellen sortierbar zu machen.

Welche Informationen benötigt ein Programm, um eine Tabelle sortieren zu können? Natürlich die Spalte, nach der sortiert werden soll, und die Richtung, also absteigend oder aufsteigend.

<ice:dataTable id="dataList"
               border="1"
               value="#{dataTableBean.bookList}"
               rows="#{dataTableBean.showRows}"
               var="row"
               sortColumn="#{bookService.sortColumn}"
               sortAscending="#{
bookService.ascending}">

Wir fügen zwei neue Attribute in unsere DataTable-Komponente ein. sortColumn gibt die Spalte an, nach der sortiert werden soll, und sortAscending gibt die Sortierrichtung an. Beides sind Informationen, die wir dynamisch aus das DataTableBean erhalten sollten, denn sie sollen ermittelt werden, wenn der Benutzer auf die entsprechende Spalte klickt.

An den Spaltendefinitionen hat sich auch etwas geändert. Knöpfen wir uns diese mal vor:

<ice:column>
     <f:facet name="header">
     <ice:commandSortHeader columnName="Author" arrow="true" >
         <ice:outputText value="Autor"/>
     </ice:commandSortHeader>

     </f:facet>
     <ice:outputText value="#{row.author}" />
</ice:column>


Wir haben eine neue Komponente eingefügt: <ice:commandSortHeader>. arrow gibt an, ob ein Pfeil angezeigt werden soll, der die Sortierrichtung angibt. Sonst müssen Sie bei commandSortHeader nicht viel tun. Der OutputText gibt die Beschriftung der Spalte an. Die anderen Spalten sehen genauso aus.

Doch woher bekommen wir die benötigten Informationen? Sehen wir uns mal unseren BookService an.

public class BookService {
    private static ArrayList<Book> bookList;
    /**
     * Spalte, nach der sortiert werden soll.
     */
    private String sortColumn;
    /**
     * True, wenn aufsteigend sortiert werden soll, sonst false.
     */
    private boolean ascending;

    public BookService() {
        sortColumn = "Id";
        ascending = true;
       
        bookList = new ArrayList<Book>();
        bookList.add(new Book(1, "Der dunkle Turm 1 - Schwarz", "Stephen King", 336));
        bookList.add(new Book(2, "Das Buch des Feuers", "James Clemens", 512));
        bookList.add(new Book(3, "Das Druidentor", "Wolfgang Hohlbein", 558));
        bookList.add(new Book(4, "Ritus", "Markus Heitz", 544));
        bookList.add(new Book(5, "Unendlichkeit", "Alastair Reynolds", 766));
        bookList.add(new Book(6, "Die Purpurinseln", "Thomas Finn", 384));
        bookList.add(new Book(7, "Der Wahrträumer", "Bernhard Hennen", 512));
        bookList.add(new Book(8, "Die Brandmauer", "Henning Mankell", 592));
        bookList.add(new Book(9, "Der Hund der Baskervilles", "Arthur Conan Doyle", 286));
    }

    public ArrayList<Book> getBookList() {
        sort();
        return bookList;
    }

    public void setBookList(ArrayList<Book> bookList) {
        BookService.bookList = bookList;
    }

    public String getSortColumn() {
        return sortColumn;
    }

    public void setSortColumn(String sortColumn) {
        this.sortColumn = sortColumn;
    }

    public boolean isAscending() {
        return ascending;
    }

    public void setAscending(boolean ascending) {
        this.ascending = ascending;
    }
   
    public void sort() {
        BookComparator comparator = new BookComparator(sortColumn, ascending);
        Collections.sort(bookList, comparator);
    }
}


Bevor wir nun die Liste mit den Büchern ausgeben, sortieren wir sie:

public ArrayList<Book> getBookList() {
     sort();
     return bookList;
}

// ......

public void sort() {
    BookComparator comparator = new BookComparator(sortColumn, ascending);
    Collections.sort(bookList, comparator);
}


Die Methode sort() erstellt ein Objekt der Klasse BookComparator. Diese Klasse benötigen wir in unserem Beispiel, aber wenn beispielsweise eine Datenbank verwendet wird, ist sie nicht mehr nötig. Denn dann können wir einfach in der select-Anweisung mit einer order-by-Klausel sortieren. Dies kann dann direkt in der Service-Klasse geschehen, welche die Daten aus der Datenbank selektiert. Doch vorerst behelfen wir uns mit dem BookComparator.

package de.myopac;
import java.util.Comparator;

public class BookComparator implements Comparator {  
    public BookComparator(String sortColumn, boolean ascending) {
        super();
        this.sortColumn = sortColumn;
        this.ascending = ascending;
    }
   
    public int compare(Object o1, Object o2) {
        Book book1 = (Book)o1;
        Book book2 = (Book)o2;
               
        if (sortColumn == null) {
            return 0;
        }
       
        // Sortieren nach der Id.
        if (sortColumn.equals("Id")) {
            if (ascending == true) {
                return new Integer(book1.getBookId()).compareTo(new Integer(book2.getBookId()));
            } else {
                return new Integer(book2.getBookId()).compareTo(new Integer(book1.getBookId()));
            }
        }
        // Sortieren nach dem Titel.
        else if (sortColumn.equals("Title")) {
            if (ascending == true) {
                return new Integer(book1.getTitle().compareTo(book2.getTitle()));
            } else {
                return new Integer(book2.getTitle().compareTo(book1.getTitle()));
            }
        }   
       
        // Sortieren nach dem Autor
        else if (sortColumn.equals("Author")) {
            if (ascending == true) {
                return new Integer(book1.getAuthor().compareTo(book2.getAuthor()));
            } else {
                return new Integer(book2.getAuthor().compareTo(book1.getAuthor()));
            }
        }       
       
        // Sortieren nach der Seitenanzahl.  
        else if (sortColumn.equals("Pages")) {
            if (ascending == true) {
                return new Integer(book1.getPages()).compareTo(new Integer(book2.getPages()));
            } else {
                return new Integer(book2.getPages()).compareTo(new Integer(book1.getPages()));
            }
        } else {
            return 0;
        }
    }
}


Diese Klasse implementiert das Interface Comparator. Die Methode compare() vergleicht zwei Objekte, hier zwei Bücher, miteinander und gibt eine entsprechende Sortierreihenfolge zurück. In der sort()-Methode von BookService werden die Daten sortiert. Die sortierte Ergebnisliste wird schließlich zurückgegeben und in der Tabelle angezeigt.

Da die sort()-Methode jedes Mal aufgerufen wird, sobald die Liste ausgegeben werden soll, und da ein Klick auf einen Spaltenkopf eine neue Ausgabe auslöst, steht in der DataTable jedes Mal die sortierte Liste.

Ich hoffe, Sie verstehen nun, wie das Sortieren funktioniert. Falls es noch Fragen oder Anregungen gibt, hinterlassen Sie bitte einen Kommentar.

In den nächsten Teilen wollen wir uns noch weitere Komponenten von IceFaces ansehen und unsere kleine Anwendung noch erweitern.

IceFaces Tutorial Teil 5 - DataTable mit Paginator


Werbung

Veröffentlicht in IceFaces

Um über die neuesten Artikel informiert zu werden, abonnieren:
Kommentiere diesen Post