views:

1010

answers:

2

I have a datatable that generates rows of text inputs and selection lists and when I submit the values are null. I realize this is because jsf is generating separate random ID's for each input. I really need the data by rows and then parse out what I need. Any suggestions?:

<h:dataTable id="returnableItems" value="#{returnableItemsBean.orderCustomerFamilyItems}" var="item" styleClass="data stripeTable center">
  <h:column>
    <f:facet name="header">Item Number</f:facet>
    <h:outputText id="itemNum" value="#{item.itemNum}"/>
  </h:column>
  <h:column>
    <f:facet name="header">Description</f:facet>
    <h:outputText value="#{item.itemDescription}"/>
  </h:column>
  <h:column>
    <f:facet name="header">Original Quantity</f:facet>
    <h:outputText value="#{item.originalQuantity}"/>
  </h:column>
  <h:column>
    <f:facet name="header">Remaining Quantity</f:facet>
    <h:outputText value="#{item.eligibleQuantity}"/>
  </h:column>
  <h:column>
    <f:facet name="header">Quantity For Return</f:facet>
    <h:panelGrid styleClass="stepper">
      <span class="ns ui-stepper">
        <input id="returnQuantity" type="text" name="returnQuantity" size="2" autocomplete="off" class="ui-stepper-textbox" value="0" />
        <button type="button" name="ns_button_1_0" value="" class="ui-stepper-plus" onclick="setMaxVal(this,#{item.eligibleQuantity});">+</button>
        <button type="button" name="ns_button_2_0" value="" class="ui-stepper-minus">-</button>
      </span>
    </h:panelGrid>
  </h:column>
  <h:column>
    <f:facet name="header">Reason for Return</f:facet>
    <h:selectOneMenu id="returnReason" value="#{returnableItemsBean.orderReason.ordReasonCode}">
      <f:selectItems value="#{returnableItemsBean.orderReasons}"/>
      <f:converter  converterId="orderReasonConverter"/>
    </h:selectOneMenu>
  </h:column>
  <h:column>
    <f:facet name="header">Return/Replacement</f:facet>
    <h:selectOneMenu id="returnOption">
      <f:selectItem itemLabel="Option" itemValue=""/>
      <f:selectItem itemLabel="Return" itemValue="return"/>
      <f:selectItem itemLabel="Replacement" itemValue="replacement"/>
    </h:selectOneMenu>
  </h:column>
</h:dataTable>
+1  A: 

I fail to understand why you use HTML input and buttons and not JSF ones in your form. Use <h:inputText> and <h:commandButton> instead, and bind their values to a property in your backing bean. The whole table should be inside a <h:form> ... </h:form> tag, of course.

Also, your input should probably be bound to a property of the "item" variable, like you do for output. If not, each row will have an input bound to the same property of your backing bean.

Are you using JSP, or Facelets ?

ckarmann
A: 

jsf is generating separate random ID's for each input

The IDs are not random; h:dataTable is a NamingContainer and manages its childrens clientIds so they become unique (a requirement of the HTML spec). JSF: working with component IDs (id vs clientId).

The straight HTML you have added will be difficult to integrate with the JSF model-view-presenter framework. It would be better to stick to JSF controls. This code shows how you can manipulate client-side field values using JavaScript and a custom TLD function:

  <h:dataTable value="#{rowDataBean.data}" var="row">
    <h:column>
      <f:facet name="header">
        <h:outputText value="product" />
      </f:facet>
      <h:outputText value="#{row.name}" />
    </h:column>
    <h:column id="column2">
      <f:facet name="header">
        <h:outputText value="quantity" />
      </f:facet>
      <h:inputText id="quantityCount" value="#{row.quantity}" />
      <h:commandButton value="+"
        onclick="increment('#{id:clientId('quantityCount')}'); return false;" />
    </h:column>
  </h:dataTable>

The invoked JavaScript:

function increment(id) {
  //TODO: error handling
  var textField = document.getElementById(id);
  var value = textField.value;
  value++;
  textField.value = value;
}

If you are using Facelets instead of JSPs, you will need to define the function in a Facelets tag library.

McDowell
I see the id on the <h:inputText in the dataTable does not change in the source so does the JSF make the IDs unique on the fly?
Martlark
Yes - the clientId is controlled by parent naming containers like UIForm (e.g. h:form) and UIData (e.g. h:dataTable) and might take the form of id="form1:table1:3:quantityCount". The EL expression within the JavaScript will be evaluated for each row as the page is rendered to the client.
McDowell
A similar example using Facelets: http://illegalargumentexception.blogspot.com/2009/05/jsf-using-component-ids-in-data-table.html
McDowell