2 Replies Latest reply on Nov 4, 2008 7:32 AM by Paul Baker

    ExtendedDataTable w/ Input Fields and Validations - Finding

    Paul Baker Apprentice

      I'm using an ExtendedDataTable and the table has input fields for several columns. If a field is found to be in error then I want to display a red background on the field. Sounds easy and it should be.

      I'm using the standard JSF converter and a phase listener. Reference:
      http://balusc.blogspot.com/2007/12/set-focus-in-jsf.html

      My problem is for each client ID that is returned from facesContext.getClientIdsWithMessages, I cannot found the matching UIComponent object when I traverse the ViewRoot.

      For example, using facesContext.getClientIdsWithMessages() is get a client id such as: j_id577:effectiveSheetForm:revision:0:sheetDate

      0 = row zero which is correct. The first date entered was invalid. However, when I traverse the view I cannot find a UIInput element with this client id. The best match is: j_id58:effectiveSheetForm:revision:sheetDate but this element is missing the row piece.

      What am I missing here?

      Thanks in advance....
      Paul

      Phase Listener:

      package com.sita.ahm565.utils;
      
      import java.util.HashSet;
      import java.util.Iterator;
      
      import javax.faces.component.UIComponent;
      import javax.faces.component.UIInput;
      import javax.faces.context.FacesContext;
      import javax.faces.event.PhaseEvent;
      import javax.faces.event.PhaseId;
      import javax.faces.event.PhaseListener;
      
      public class SetClearErrorStyle implements PhaseListener {
       /**
       *
       */
       private static final long serialVersionUID = 1L;
       HashSet<String> errorIds = new HashSet<String>();
       FacesContext facesContext;
      
       /**
       * @see javax.faces.event.PhaseListener#getPhaseId()
       */
       public PhaseId getPhaseId() {
      
       // Listen on render response phase.
       return PhaseId.RENDER_RESPONSE;
       }
      
       /**
       * @see javax.faces.event.PhaseListener#beforePhase(javax.faces.event.PhaseEvent)
       */
       public void beforePhase(PhaseEvent event) {
       System.out.println("Phase Start");
       facesContext = event.getFacesContext();
       Iterator<String> clientIdsWithMessages = facesContext.getClientIdsWithMessages();
       while (clientIdsWithMessages.hasNext()) {
       errorIds.add(clientIdsWithMessages.next());
       }
      
       if (errorIds.size() > 0)
       setResetStyles(facesContext.getViewRoot());
       }
      
       /**
       * @see javax.faces.event.PhaseListener#afterPhase(javax.faces.event.PhaseEvent)
       */
       public void afterPhase(PhaseEvent event) {
       // Do nothing.
       }
      
       public void setResetStyles(UIComponent pComponent) {
       String styleClass;
       if (pComponent instanceof UIInput) {
       if (errorIds.contains(pComponent.getClientId(facesContext))) {
       styleClass = (String) pComponent.getAttributes().get("styleClass");
       System.out.println("Error Field Found with Style " + styleClass);
       }
       }
      
       Iterator<UIComponent> children = pComponent.getFacetsAndChildren();
       while (children.hasNext()) {
       setResetStyles(children.next());
       }
       }
      }



      Facelet with the ExtendedDataTable:

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      
      <html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:rich="http://richfaces.ajax4jsf.org/rich"
       xmlns:a4j="http://richfaces.org/a4j"
       xmlns:c="http://java.sun.com/jstl/core"
       xmlns:f="http://java.sun.com/jsf/core" xml:lang="en" lang="en">
      
       <body>
      
       <center>
       <h:outputLabel value="List of Effective Sheets"
       styleClass="TitleNormal" />
       </center>
      
       <ui:include src="/messages.xhtml" />
      
       <a4j:keepAlive beanName="effectiveSheetController" />
      
       <a4j:form id="effectiveSheetForm">
       <center>
       <h:panelGrid columns="1">
       <h:panelGroup>
       <rich:spacer height="5" />
       <rich:extendedDataTable id="revision"
       value="#{effectiveSheetController.value}" var="item"
       rowKeyVar="idx" selectionMode="single" width="740px"
       height="450px" cellpadding="0" cellspacing="0">
       <rich:column id="selected" sortable="false" width="30px"
       label="Select">
       <f:facet name="header">
       <h:outputText value="Sel" />
       </f:facet>
       <h:selectBooleanCheckbox value="#{item.selected}">
       </h:selectBooleanCheckbox>
       </rich:column>
      
       <rich:column id="section" sortable="true" headerClass="CHfw80"
       sortBy="#{item.section}" filterBy="#{item.section}"
       filterEvent="onkeyup" width="100px" label="Section">
       <f:facet name="header">
       <h:outputText>Section</h:outputText>
       </f:facet>
       <h:inputText value="#{item.section}" styleClass="InpNormal"
       size="12" />
       </rich:column>
      
       <rich:column id="sheet" sortable="true" headerClass="CHfw80"
       sortBy="#{item.sheet}" filterBy="#{item.sheet}"
       filterEvent="onkeyup" width="100px" label="Sheet">
       <f:facet name="header">
       <h:outputText>Sheet</h:outputText>
       </f:facet>
       <h:inputText value="#{item.sheet}" styleClass="InpNormal"
       size="12" />
       </rich:column>
      
       <rich:column id="multiPageid" sortable="true"
       headerClass="CHfw80" sortBy="#{item.multiplePageIdentifier}"
       filterBy="#{item.multiplePageIdentifier}" filterEvent="onkeyup"
       width="100px" label="Muliple Page Id">
       <f:facet name="header">
       <h:outputText>Multiple<br />Page Id</h:outputText>
       </f:facet>
       <h:inputText value="#{item.multiplePageIdentifier}"
       styleClass="InpNormal" size="12">
       </h:inputText>
       </rich:column>
      
       <rich:column id="effectiveSheetDate" sortable="true"
       headerClass="CHfw80" sortBy="#{item.effectiveSheetDate}"
       filterBy="#{item.effectiveSheetDate}" filterEvent="onkeyup"
       width="100px" label="Date">
       <f:facet name="header">
       <h:outputText>Date</h:outputText>
       </f:facet>
       I want to find this UIComponent ->>>> <h:inputText id="sheetDate" value="#{item.effectiveSheetDate}"
       styleClass="InpNormal" size="12">
       <f:convertDateTime pattern="yyyy-MM-dd" />
       </h:inputText>
       </rich:column>
      
      
       </rich:extendedDataTable>
       <h:panelGrid columns="1" width="740px" style="text-align: right">
       <h:panelGrid columns="3"
       columnClasses="CtaLw50P, CtaRw50P,CtaLw50P" width="740px">
       <h:commandButton id="delete" value="Delete Selected"
       action="#{effectiveSheetController.deleteSelected}"
       styleClass="BtnSmall" />
       <h:outputText value="Blank Lines:" styleClass="LblNormal" />
       <rich:inputNumberSpinner inputSize="2" enableManualInput="false"
       value="#{effectiveSheetController.blankLines}">
       <a4j:support requestDelay="500" ignoreDupResponses="true"
       actionListener="#{effectiveSheetController.updBlankLines}"
       event="onchange" reRender="revision" />
       </rich:inputNumberSpinner>
       </h:panelGrid>
       </h:panelGrid>
       <rich:spacer height="5" />
       <center>
       <a4j:commandButton value="Update"
       reRender="contentPage"
       action="#{effectiveSheetController.updateAcType}" />
       </center>
       </h:panelGroup>
       </h:panelGrid>
       </center>
       </a4j:form>
       </body>
      </html>