0
votes

I am using JSF 2.3 and Bootsfaces 3.3 in a small web application. I stumbled upon a scenario where Bootsfaces' <b:commandButton ajax=true ...> raises an exception while <h:commandButton>+<f:ajax> does not. Looking at the exception that gets raised Bootsfaces is not able to find the element with the given ID that should be updated in the render response phase ("ajaxUpdateMe" in the examples below).

I played around the xhtml page to nail down where the actual problem is and to me it looks like <ui:repeat ...> and an ajaxafied <b:commandButton> is not working well together. This is the (stripped down version of the) xhtml page that I am using (minus <html> and <head> parts):

<h:body>
  <b:form id="formTable">
    <!-- iterate over list of objects -->
    <ui:repeat value="#{testBean.list}" var="element">
      <b:row>
        <b:column><h:outputText id="ajaxUpdateMe" value="#{element.name}" /></b:column>
      </b:row>
      <b:row>
        <b:column>
          <!-- iterate over another list -->
          <h:dataTable value="#{element.innerList}" var="inner">
            <h:column>
              <b:commandButton ajax="true" value="submit"
                   action="#{testBean.submit(element)}"
                   update=":#{component.namingContainer.parent.namingContainer.clientId}:ajaxUpdateMe"
                   process="@this" />
            </h:column>
          </h:dataTable>
        </b:column>
      </b:row>
    </ui:repeat>
  </b:form>
</h:body>

When I try to access the xhtml page through the browser (GET request) then an exception is immediately raised that looks like this (shortened for sake of brevity):

Caused by: javax.faces.FacesException: Invalid search expression: formTable:j_idt4:0:ajaxUpdateMe The subexpression 0 doesn't exist, or it can't be resolved. net.bootsfaces.component.commandButton.CommandButton  formTable:j_idt4:0:j_idt9:0:j_idt13  Additional information: ID not found: 0 search expression: formTable:j_idt4:0:ajaxUpdateMe
    at net.bootsfaces.expressions.ExpressionResolver.translateSearchExpressionToId(ExpressionResolver.java:143)
    at net.bootsfaces.expressions.ExpressionResolver.getComponentId(ExpressionResolver.java:89)
    at net.bootsfaces.expressions.ExpressionResolver.getComponentIDs(ExpressionResolver.java:50)
    at net.bootsfaces.expressions.ExpressionResolver.getComponentIDs(ExpressionResolver.java:44)
    at net.bootsfaces.component.ajax.AJAXRenderer.generateAJAXCallForClientBehavior(AJAXRenderer.java:582)
    at net.bootsfaces.component.ajax.AJAXRenderer.generateBootsFacesAJAXAndJavaScript(AJAXRenderer.java:233)
    at net.bootsfaces.component.ajax.AJAXRenderer.generateBootsFacesAJAXAndJavaScript(AJAXRenderer.java:177)
    at net.bootsfaces.component.commandButton.CommandButtonRenderer.encodeBegin(CommandButtonRenderer.java:120)
    at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:892)
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:307)
    at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:114)
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:918)
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:309)
    at com.sun.faces.renderkit.html_basic.TableRenderer.renderRow(TableRenderer.java:398)
    at com.sun.faces.renderkit.html_basic.TableRenderer.encodeChildren(TableRenderer.java:161)

I replaced the command button from Bootsfaces with this code here:

<h:commandButton value="submit"
                 action="#{testBean.submit(element)}">
  <f:ajax render=":#{component.namingContainer.parent.namingContainer.clientId}:ajaxUpdateMe"
           execute="@this"/>
</h:commandButton>

Now the page loads fine and the command button does what it should do. Checking the source of the html page in the browser I can see that the element that is mentioned in the exception message formTable:j_idt4:0:ajaxUpdateMe is actually there.

Did I hit a bug in Bootsfaces or am I doing something wrong? Does someone know a workaround where I can still use the command button from Bootsfaces?

1

1 Answers

0
votes

It looks like BootsFaces ID resolver strugles with the 0 in formTable:j_idt4:0:ajaxUpdateMe. You can try to add an id="elements to the ui:repeat and then directly reference the target component via :formTable:elements:ajaxUpdateMe.

<h:body>
  <b:form id="formTable">
    <!-- iterate over list of objects -->
    <ui:repeat id="elements" value="#{testBean.list}" var="element">
      <b:row>
        <b:column><h:outputText id="ajaxUpdateMe" value="#{element.name}" /></b:column>
      </b:row>
      <b:row>
        <b:column>
          <!-- iterate over another list -->
          <h:dataTable value="#{element.innerList}" var="inner">
            <h:column>
              <b:commandButton ajax="true" value="submit"
                   action="#{testBean.submit(element)}"
                   update=":#formTable:elements:ajaxUpdateMe"
                   process="@this" />
            </h:column>
          </h:dataTable>
        </b:column>
      </b:row>
    </ui:repeat>
  </b:form>
</h:body>

My IDE does not suggest ui:repeat actually has an id attribute, but it somehow works for me.

Alternatively you can add a standard f:ajax to your button:

<b:commandButton ajax="true" value="submit" process="@this">
    <f:ajax render=":#{component.namingContainer.parent.namingContainer.clientId}:ajaxUpdateMe" />
</b:commandButton>

I'm not sure if this is to be considered a bug. You may want to bring this up in their issue tracker