# Probleme mit Facelets und if foreach und when



## thajek (7. Nov 2007)

*Bitte den anderen Thread löschen*

Hallo ich habe folgende Problem:

Kurz zum aufbau ich habe eine list mit SearchType objecten diese iteriere ich mit eine c:foreach schleife durch. In der foreach schleife frage ich mit c:if oder c:when den type ab und verändere demensprechen das ausehen.
Die JSF läuft als portlet in einem BenutzerPortal von Novell

und zwar wird die anzeige durch die c:foreach und c:if variable generiert wenn ich nun zwei inputText habe und einen davon lösche kommt es zu einem fehler und zwar wird die variable i zwar in der foreach schleife richtig hochgezählt aber im c:when block nochmals um einen inkrementiert. Dies geschieht allerdings nur wenn ich ein inputText lösche das ein nicht String type hatte.

Das heisst ich füge ein neue h:inputText hinzu welches an ein Date object gebunden wird, nun lösche ich den h:inputText der über diesen ist. Intern (durch Debuggen getestet) kommt es zu keinen fehler die Liste mit den Objecten wird richtig veringert. Doch troztdem kommt es zu dem Fehler das die variable i in den c:while oder eben c:if um eins höher ist als sie sein sollten

Das komische ist es passiert nur wenn der h:inputText (der keine String bindung hat) unterhalb des inputTextes ist. Zudem kommt dieses problem nicht vor wenn ich die h:inputText nur mit String objecten Binde

Wenn ich mir die variable i ausgeben lasse wird sie wie folgt ausgegeben

Ablauf
foreach i = 0
when i = 1
danach wieder i=0

auserhalb von when ist die variable i so wie sie sein sollte

es sieht auch so aus als ob das ein problem vom Framework ist

In der Klasse search (ein kleiner teil) 

```
public void deleteSearch(int item)
   {
      list.remove(item);
   }
   public void addSearch()
   {
      SearchType tempSearchType;
      String tempType = getTypeByName(newAttribute);
      Attribute tempAttr = getAttributeByName(newAttribute);
      if(tempType.equals("date") || tempType.equals("unixtimestamp"))
      {
         tempSearchType = new SearchType(new Date(),tempAttr,"=var");
      }
      else if(tempType.equals("boolean"))
      {
         tempSearchType = new SearchType(Boolean.valueOf(false),tempAttr,"=var*");
      }
      else if(tempType.equals("int"))
      {
         tempSearchType = new SearchType(Integer.valueOf(0),tempAttr,"=var*");
      }
      else
      {
         tempSearchType = new SearchType("test",tempAttr,"=var*");
      }
      list.add(tempSearchType);
   }
```
In der Klasse searchType (ein kleiner teil) 

```
public String getString()
   {
      if(attr instanceof String)
      {
         return (String) attr;
      }
      else
      {
         return null;
      }
   }
   
   public Date getDate()
   {
      if(attr instanceof Date)
      {
         return (Date) attr;
      }
      else
      {
         return null;
      }
   }
```
list.jsp

```
<h:panelGrid columns="4" >
         <c:forEach begin="0" end="#{controller.search.searchSize}" var="i" >
               <c:set value="#{controller.search.list[i]}" var="search"/>
               <c:set value="#{search.attribute.type}" var="type"/>
             <c:choose>
               <c:when test="#{type == 'int'}">
                  <h:inputText value="#{search.int}"/>
                  <h:outputText value="#{search.attribute.displayName}" />
                  <h:selectOneMenu  value="#{search.criterion}">
                           <f:selectItems value="#{search.criterionByType}" />
                  </h:selectOneMenu>
                  <h:commandButton class="goeUserInPortletCommandButton"  id="searchDelete#{i}"  value="löschen"
                     actionListener="#{controller.deleteSearch}"/>
               </c:when>
               <c:when test="#{type == 'boolean'}">
                  <h:inputText value="#{search.boolean}"/>
                  <h:outputText value="#{search.attribute.displayName}" />
                  <h:selectOneMenu  value="#{search.criterion}">
                           <f:selectItems value="#{search.criterionByType}" />
                  </h:selectOneMenu>
                  <h:commandButton class="goeUserInPortletCommandButton"  id="searchDelete#{i}" value="löschen"
                     actionListener="#{controller.deleteSearch}"/>
               </c:when>
               <c:when test="#{type == 'date' or type == 'unixtimestamp'}">
                  <t:inputDate
                        value="#{search.date}" popupCalendar="false">
                  </t:inputDate>
                  <h:inputText value="#{controller.search.list[i].date}"/>
                  <h:selectOneMenu  value="#{search.criterion}">
                           <f:selectItems value="#{search.criterionByType}" />
                  </h:selectOneMenu>
                  <h:outputText value="#{controller.search.list[i].attribute.displayName}" />
                  <h:commandButton class="goeUserInPortletCommandButton"  id="searchDelete#{i}" value="löschen"
                     actionListener="#{controller.deleteSearch}"/>
               </c:when>
               <c:when test="#{type == 'string'}">
                  <h:inputText value="#{search.string}"/>
                  <h:selectOneMenu  value="#{search.criterion}">
                     <f:selectItems value="#{search.criterionByType}"/>
                  </h:selectOneMenu>
                  <h:outputText value="#{search.attribute.displayName}">
                  </h:outputText>
                  <h:commandButton class="goeUserInPortletCommandButton"  id="searchDelete#{i}"  value="löschen" actionListener="#{controller.deleteSearch}"/>
               </c:when>
            </c:choose>
               </c:forEach>
          <h:selectOneMenu id="searchtype" value="#{controller.search.linkage}">
            <f:selectItem itemValue="and" itemLabel="AND" />
            <f:selectItem itemValue="or" itemLabel="OR" />
         </h:selectOneMenu>
         <h:selectOneMenu value="#{controller.search.newAttribute}">
            <f:selectItems value="#{controller.selectAttributes}" />
         </h:selectOneMenu>
         <h:commandButton class="goeUserInPortletCommandButton" disabled="#{editable}" value="hinzufügen"
                              actionListener="#{controller.addSearch}"/>
         <h:commandButton class="goeUserInPortletCommandButton" action="#{controller.searchUsers}" value="Suchen" />               
      
</h:panelGrid>
```


----------



## JimPanse (8. Nov 2007)

Hallo erstmal,

also ich arbeite mit JSF und Portlets jetzt nen hlbes Jahr und kann nur davon abraten JSF und JSTL zu mischen!

Ich würde deine List in eine <h:datatable> packen und die Operationen auf die Liste kannst du dann ganz einfach über deine Bean machen, in dem du ein Komponenten Binding verwendest!

BSP.

import javax.faces.component.html.HtmlDataTable;

class DeineBean{

private HtmlDataTable deineTable;
private List<Item> liste;
private Item chItem;

 public getRowData(){
   Item item2Remove = (Item) deineTable.getRowData();
   liste.remove(item2Remove);
 } 

}


JSF QellText:

<h:datatable
value="#{DeineBean.liste}"
binding="#{DeineBean.deineTable}"
var="liste">
 <h:column>
   ...Attribute des Item
</h:column>

</h:datatable>


So ich hoffe ich hab deine Frage ungefähr verstanden und auch dir weiterhelfen können.

MfG


----------



## JimPanse (8. Nov 2007)

Soory vergesse immer die Code Tags zu verwenden:



```
import javax.faces.component.html.HtmlDataTable; 

class DeineBean{ 

private HtmlDataTable deineTable; 
private List<Item> liste; 
private Item chItem; 

    public getRowData(){ 
        Item item2Remove = (Item) deineTable.getRowData(); 
        liste.remove(item2Remove); 
    } 

} 


JSF QellText: 

<h:datatable 
value="#{DeineBean.liste}" 
binding="#{DeineBean.deineTable}" 
var="liste"> 
<h:column> 
...Attribute des Item 
</h:column> 

</h:datatable>
```


----------



## thajek (8. Nov 2007)

*Danke für die antwort*, das problem ist viel mehr das ich in der list variable h:inputText und zbp t:inputDate wechseln möchte und das geht leider so weit ich das übersehe nur mit jstl c:if oder c:when da ich in eine h:dataTable auch kein c:if benutzen kann da das komplett versagt. Ich habe es jetzt auch so gemacht das ich nur h:inputText verwende und eigendlich die c:foreach schleife nichtmehr brauche und ein h:dataTable nehmen könnte habe da aber das problem das ich eben nicht verschiedene ausehen erstellen kann.

Dazu kommt noch das ich es nicht hinbekommen habe mit facelets renderer zu scheiben welches mir auch das problem lösen würde. Vieleicht weiss ja jemand wo eine gut beschreibung ist oder wo der unterschied ligt zwischen einenm normalem renderer in jsf und unter facelets


----------

