Moin ihr Lieben,
Ich hatte vor ein paar tagen im WebTier diesen Post abgesetzt:
http://www.java-forum.org/web-tier/140090-h-datatable-p-komponente-pagination-buchstaben.html
Bezugnehmend dazu, möchte ich nun meine Lösung präsentieren, da ich im Web weder auf Englisch noch auf Deutsch einen Passenden Beitrag gefunden habe wie man soetwas umsetzen könnte.
Was wollte ich denn Eigentlich umsetzen? Nun wenn man es genau nimmt, eine Normale Pagination mit "Zurück" und "Weiter", sowie die Sprungfunktion nach Buchstaben wie Outlook sie in seinen Kontakten hat. Wie das ganze ( Ohne ins Design eingebunden zu sein) aussieht, könnt ihr im Anhang sehen.
Die von mir implementiert Umsetzung ist noch ein wenig "roh" oder "brutal" wenn man so will, es kann sicherlich noch Einiges optimiert werden.
Desweiteren benutze ich Primefaces DataGrid. Der vorteil dabei ist, dass ich mich bei Primefaces nicht weiter um den Ajax-Support kümmern muss. Eure Umsetzung für einen normalen h:dataTable müsste dann dementsprechend umgebaut / erweitert werden.
Nun zur Umsetzung.
1. Elemente zählen.
jeh nach dem wie eure Datenstruktur aussieht, ist das Zählen von Elementen einfacher oder schwerer.
Ich bekomme einfach eine Liste mit Adressen. Diese Liste muss ich "durchzählen" oder aufsplitten.
Denn wir müssen wissen, wie viele Elemente in den jeweiligen Untermengen ( 'A', 'B', 'C',...'Z','Zahlen+Sonderzeichen' ) enthalten sind.
Dieses "durchzählen" habe ich recht brutal durch einen verdammt langen Switch-Case gelöst. Lasst euch durch diesen Snipped nicht entmutigen, es ist der "unschönste" bei der ganzen sache.
Code 1: Elemente Zählen
Das war ja schon mal ein Brocken an Code aber keine Angst, es wird nun chilliger.
2. Zeilen herausfinden.
Nun muss man sich überlegen, wohin man eigentlich sprinegn will.
Die Antwort: Zum ersten element der Untermenge 'A', 'B', 'C'... oder 'Z'. Das hat mich recht viel Nachdenken gekostet, bis ich mathematisch dahinter gekommen bin wie man das lösen kann. Wenn man es erstmal hat, ist es einfach.
Die alphabetisch größere Untermenge fängt nach dem letzten Elememt der vorangegangenen Menga an.
Also wenn 'A' = 5 Elemente dann fängt 'B' bei 6 an. Das müssen wir aufaddieren. Ein Schriftliches beispiel:
Wir wollen wissen wo C anfängt:
A=10 Elemente
B= 21 Elemente
C=3 Elemente
A + B = 31 --> C fängt bei 32 an und hört bei 34 auf. Wenn wir schon mal bei 34 sind, D fängt somit bei 35 an.
Code 2: Elemente aufaddieren.
So das wars mit der Vorbereitung. Nun können wir das in ner ManagedBean benuzen und es wird ein wenig Interessanter.
3. Setzen von "first" für die h:dataTable bzw. das p:dataGrid
h:datatable und p:dataGrid besitzen das Attribut first. Darüber wird angegeben in welcher Zeile man anfangen möchte. Wir schauen uns zuerst mal die JSF-Seite (xhtml) an.
Code 3: Die JSF Seite:
[XML]
<div style="hight: 60px; width: 1024px;">
<!-- ALLE BUTTONNS VON A bis Z -->
<hanelGrid columns="13">
<p:commandButton value="A" action="#{institutionAdressBean.setFirstRow( '-1' )}" update="adrList" style="width: 50px;" ></p:commandButton>
<p:commandButton value="B" action="#{institutionAdressBean.setFirstRow( '0' )}" update="adrList" style="width: 50px;"></p:commandButton>
<p:commandButton value="C" action="#{institutionAdressBean.setFirstRow( '1' )}" update="adrList" style="width: 50px;"></p:commandButton>
<!--- UND SO WEITER --->
<p:commandButton value="X" action="#{institutionAdressBean.setFirstRow( '22' )}" update="adrList" style="width: 50px;"></p:commandButton>
<p:commandButton value="Y" action="#{institutionAdressBean.setFirstRow( '23' )}" update="adrList" style="width: 50px;"></p:commandButton>
<p:commandButton value="Z" action="#{institutionAdressBean.setFirstRow( '24' )}" update="adrList" style="width: 50px;"></p:commandButton>
</hanelGrid>
</div>
<br/>
<!---WEITER UND ZURÜCK BUTTON--->
<center>
<div style="margin-left: auto; margin-right: auto;">
<p:commandButton value="Zurück" action="#{institutionAdressBean.setFirstRowPagination('-1')}" update="adrList" />
<p:commandButton value="Weiter" action="#{institutionAdressBean.setFirstRowPagination('1')}" update="adrList" />
</div>
</center>
<br/>
<div style="width: 1024px;" >
<p:dataGrid id="adrList" var="adr" value="#{institutionAdressBean.selectetAddresses}" columns="3"
rows="12"
paginator="false"
style="min-width:1024px; min-height: 1200px;"
first="#{institutionAdressBean.firstRow}">
<p:column>
<panel header="#{adr.nachname}" style="text-align:left; max-width: 300px;">
<hanelGrid columns="2" style="width:300px;">
Name: <hutputText value="#{adr.nachname}" />
Vorname: <hutputText value="#{adr.vorname}" />
Telefon: <hutputText value="#{adr.telefonGesch}" />
Handy:<hutputText value="#{adr.handyGesch}" />
</hanelGrid>
</panel>
</p:column>
</p:dataGrid>
</div>
[/XML]
Wie wir sehen rufe ich jeweils eine Aktionmethode auf, wenn ich zu 'A', 'B' oder 'C' springen will und eine für weiter und zurück. Desweiteren "update" ich das DataGrid per AJAX und setze innerhalb der Bean das Attribut "first".
Vorweg sollte gesagt sein: Ich lasse 12 Elemente anzeigen, Daher die ->12<- bei Weiter und Zurück.
Dazu hier mal die ManagedBean:
Code 4: Die ManagedBean
So das war es. Ich hoffe ihr könnt damit was anfangen. Ich würde mich freuen, wenn ihr das ganze auch noch diskutieren würdet. Man lernt ja nur dazu
in diesem Sinne!
LG
David
Ich hatte vor ein paar tagen im WebTier diesen Post abgesetzt:
http://www.java-forum.org/web-tier/140090-h-datatable-p-komponente-pagination-buchstaben.html
Bezugnehmend dazu, möchte ich nun meine Lösung präsentieren, da ich im Web weder auf Englisch noch auf Deutsch einen Passenden Beitrag gefunden habe wie man soetwas umsetzen könnte.
Was wollte ich denn Eigentlich umsetzen? Nun wenn man es genau nimmt, eine Normale Pagination mit "Zurück" und "Weiter", sowie die Sprungfunktion nach Buchstaben wie Outlook sie in seinen Kontakten hat. Wie das ganze ( Ohne ins Design eingebunden zu sein) aussieht, könnt ihr im Anhang sehen.
Die von mir implementiert Umsetzung ist noch ein wenig "roh" oder "brutal" wenn man so will, es kann sicherlich noch Einiges optimiert werden.
Desweiteren benutze ich Primefaces DataGrid. Der vorteil dabei ist, dass ich mich bei Primefaces nicht weiter um den Ajax-Support kümmern muss. Eure Umsetzung für einen normalen h:dataTable müsste dann dementsprechend umgebaut / erweitert werden.
Nun zur Umsetzung.
1. Elemente zählen.
jeh nach dem wie eure Datenstruktur aussieht, ist das Zählen von Elementen einfacher oder schwerer.
Ich bekomme einfach eine Liste mit Adressen. Diese Liste muss ich "durchzählen" oder aufsplitten.
Denn wir müssen wissen, wie viele Elemente in den jeweiligen Untermengen ( 'A', 'B', 'C',...'Z','Zahlen+Sonderzeichen' ) enthalten sind.
Dieses "durchzählen" habe ich recht brutal durch einen verdammt langen Switch-Case gelöst. Lasst euch durch diesen Snipped nicht entmutigen, es ist der "unschönste" bei der ganzen sache.
Code 1: Elemente Zählen
Java:
public class AddressHandler{
//Die Liste in die wir unsere Zählung abspeichern, könnte auch ein Array sein.
private final List<Integer> addressCount = new ArrayList<Integer>();
..
..
private void countAddresses() {
//Da wir eine Liste benutzen, müssen wir erstmal vorinitialisieren.
//Hier zeigt sich, das ein Array eventuell besser wäre :D
// Liste an der Stelle 0 ist A und Stelle 26 sind Zahlen und Sonderzeichen
//Das wird dann dementsprechend hochgezählt.
for (char c = 'A'; c <= 'Z' + 1; c++) {
addressCount.add(0);
}
//Wir Itterieren über alle Adressen und schauen uns den ersten Buchstaben des Nachnamen an
// Ergo -> ich sortiere nach Nachnamen.
for (InstitutionOrPrivateAddress a : addresses) {
//Gib mir den ersten Buchstaben des Nachnamen
switch (a.getNachname().charAt(0)) {
//Wenn erster Buchstabe 'A' -> A um eins in der liste hochzählen.
case 'A':
addressCount.set(0, addressCount.get(0) + 1);
break;
//!!! WICHTIG: Ich zähle umlaute zu dem jehweiligen buchstaben
// ALSO: Ä gehört zu A
case 'Ä':
addressCount.set(0, addressCount.get(0) + 1);
break;
case 'B':
addressCount.set(1, addressCount.get(1) + 1);
break;
case 'C':
addressCount.set(2, addressCount.get(2) + 1);
break;
...
...
...
...
case 'X':
addressCount.set(23, addressCount.get(23) + 1);
break;
case 'Y':
addressCount.set(24, addressCount.get(24) + 1);
break;
case 'Z':
addressCount.set(25, addressCount.get(25) + 1);
break;
//Das ganze nochmal für lowercase
//Man kann sich ja auch mal verschrieben haben ;)
case 'a':
addressCount.set(0, addressCount.get(0) + 1);
break;
case 'ä':
addressCount.set(0, addressCount.get(0) + 1);
break;
case 'b':
addressCount.set(1, addressCount.get(1) + 1);
break;
case 'c':
addressCount.set(2, addressCount.get(2) + 1);
break;
...
...
...
...
case 'y':
addressCount.set(24, addressCount.get(24) + 1);
break;
case 'z':
addressCount.set(25, addressCount.get(25) + 1);
break;
default:
addressCount.set(26, addressCount.get(26) + 1);
break;
}//Ende Switch
}//End For
// Zu dieser Methode kommen wir gleich
countRows();
}
}
Das war ja schon mal ein Brocken an Code aber keine Angst, es wird nun chilliger.
2. Zeilen herausfinden.
Nun muss man sich überlegen, wohin man eigentlich sprinegn will.
Die Antwort: Zum ersten element der Untermenge 'A', 'B', 'C'... oder 'Z'. Das hat mich recht viel Nachdenken gekostet, bis ich mathematisch dahinter gekommen bin wie man das lösen kann. Wenn man es erstmal hat, ist es einfach.
Die alphabetisch größere Untermenge fängt nach dem letzten Elememt der vorangegangenen Menga an.
Also wenn 'A' = 5 Elemente dann fängt 'B' bei 6 an. Das müssen wir aufaddieren. Ein Schriftliches beispiel:
Wir wollen wissen wo C anfängt:
A=10 Elemente
B= 21 Elemente
C=3 Elemente
A + B = 31 --> C fängt bei 32 an und hört bei 34 auf. Wenn wir schon mal bei 34 sind, D fängt somit bei 35 an.
Code 2: Elemente aufaddieren.
Java:
//Die Methode wird nach dem "Durchzählen" aufgerufen, ihr erinnert euch?
private void countRows() {
//Da ich die Methode auch nach einem Update aufrufem schmeiße ich erstmal alles raus.
rowCount.clear();
// A fängt IMMER bei Zeile 0 an
rowCount.add(addressCount.get(0));
int tmpI = addressCount.get(0);
// Für alle gezählten Untermengen
for (int i = 1; i < addressCount.size(); i++) {
//Addiere bis nach hinten auf
tmpI += addressCount.get(i);
rowCount.add(tmpI);
}
}
So das wars mit der Vorbereitung. Nun können wir das in ner ManagedBean benuzen und es wird ein wenig Interessanter.
3. Setzen von "first" für die h:dataTable bzw. das p:dataGrid
h:datatable und p:dataGrid besitzen das Attribut first. Darüber wird angegeben in welcher Zeile man anfangen möchte. Wir schauen uns zuerst mal die JSF-Seite (xhtml) an.
Code 3: Die JSF Seite:
[XML]
<div style="hight: 60px; width: 1024px;">
<!-- ALLE BUTTONNS VON A bis Z -->
<hanelGrid columns="13">
<p:commandButton value="A" action="#{institutionAdressBean.setFirstRow( '-1' )}" update="adrList" style="width: 50px;" ></p:commandButton>
<p:commandButton value="B" action="#{institutionAdressBean.setFirstRow( '0' )}" update="adrList" style="width: 50px;"></p:commandButton>
<p:commandButton value="C" action="#{institutionAdressBean.setFirstRow( '1' )}" update="adrList" style="width: 50px;"></p:commandButton>
<!--- UND SO WEITER --->
<p:commandButton value="X" action="#{institutionAdressBean.setFirstRow( '22' )}" update="adrList" style="width: 50px;"></p:commandButton>
<p:commandButton value="Y" action="#{institutionAdressBean.setFirstRow( '23' )}" update="adrList" style="width: 50px;"></p:commandButton>
<p:commandButton value="Z" action="#{institutionAdressBean.setFirstRow( '24' )}" update="adrList" style="width: 50px;"></p:commandButton>
</hanelGrid>
</div>
<br/>
<!---WEITER UND ZURÜCK BUTTON--->
<center>
<div style="margin-left: auto; margin-right: auto;">
<p:commandButton value="Zurück" action="#{institutionAdressBean.setFirstRowPagination('-1')}" update="adrList" />
<p:commandButton value="Weiter" action="#{institutionAdressBean.setFirstRowPagination('1')}" update="adrList" />
</div>
</center>
<br/>
<div style="width: 1024px;" >
<p:dataGrid id="adrList" var="adr" value="#{institutionAdressBean.selectetAddresses}" columns="3"
rows="12"
paginator="false"
style="min-width:1024px; min-height: 1200px;"
first="#{institutionAdressBean.firstRow}">
<p:column>
<panel header="#{adr.nachname}" style="text-align:left; max-width: 300px;">
<hanelGrid columns="2" style="width:300px;">
Name: <hutputText value="#{adr.nachname}" />
Vorname: <hutputText value="#{adr.vorname}" />
Telefon: <hutputText value="#{adr.telefonGesch}" />
Handy:<hutputText value="#{adr.handyGesch}" />
</hanelGrid>
</panel>
</p:column>
</p:dataGrid>
</div>
[/XML]
Wie wir sehen rufe ich jeweils eine Aktionmethode auf, wenn ich zu 'A', 'B' oder 'C' springen will und eine für weiter und zurück. Desweiteren "update" ich das DataGrid per AJAX und setze innerhalb der Bean das Attribut "first".
Vorweg sollte gesagt sein: Ich lasse 12 Elemente anzeigen, Daher die ->12<- bei Weiter und Zurück.
Dazu hier mal die ManagedBean:
Code 4: Die ManagedBean
Java:
@ManagedBean
@ViewScoped
public class InstitutionAdressBean {
// Die Variable für das "first"
private int firstRow = 0;
//Einbinden der andern bean, mit den Adressen und den Counts per DI
/** Creates a new instance of InstitutionAdressBean */
public InstitutionAdressBean() {
}
@ManagedProperty(value = "#{global}")
private GlobalAdressHandler globalAdressHandler;
public void setGlobalAdressHandler(GlobalAdressHandler adressHandler) {
this.globalAdressHandler = adressHandler;
}
//Gettermethode für die Adress-Liste. Wird vom DataGrid benötigt.
// Unsere Adressen halt ;)
public List<InstitutionOrPrivateAddress> getSelectetAddresses() {
return globalAdressHandler.getAddresses();
}
//Getter für das "first"-Attribut
public int getFirstRow() {
return firstRow;
}
//Setter für A - Z
public void setFirstRow(int firstRow) {
// Wenn -1 dann wollen wir A haben und A fängt immer bei 0 an
if (firstRow == -1) {
this.firstRow = 0;
} else {
//Ansonsten gib uns die aufsummierten Zeilen zurück
//Refferenz: CODE 2: Elemente aufaddieren
this.firstRow = globalAdressHandler.getRowCount().get(firstRow);
}
}
//Das setzen von "first" bei Weiter oder Zurück
public void setFirstRowPagination(int firstRow){
// -1 für Seite zurück
if(firstRow == -1){
if(this.firstRow>12){
this.firstRow -= 12;
}else{
this.firstRow=0;
}
}//Ende Zurück
//1 für eine Seite weiter
if(firstRow == 1){
if(this.firstRow < globalAdressHandler.getAddresses().size()-12){
this.firstRow += 12;
}else{
double tmpD = globalAdressHandler.getAddresses().size() / 12;
int tmpInt = (int)tmpD;
this.firstRow = tmpInt +1;
}
}// Ende Weiter
}
}
So das war es. Ich hoffe ihr könnt damit was anfangen. Ich würde mich freuen, wenn ihr das ganze auch noch diskutieren würdet. Man lernt ja nur dazu
in diesem Sinne!
LG
David
Anhänge
Zuletzt bearbeitet: