3 Replies Latest reply on Nov 29, 2011 5:13 PM by Scott Balmos

    Dynamic rich:tabPanel cannot switch tabs

    Scott Balmos Newbie

      Hello,

       

      Under both RF 4 and RF 4.1 CR1, I have a dynamic tabPanel that I'm building with c:forEach. The page renders fine. But due to some form of TypeError in an unknown location in JSF's/RF's Javascript, no click handler is registered on the tabs. This only occurs when dynamically building the tabs - hardcoded tabs work fine. Ideas please? See a condensed form of my code below:

       

      The exact JS error in Chrome is:

      Uncaught TypeError: undefined is not a function

      CALL_NON_FUNCTION_AS_CONSTRUCTOR() at (internal script):417

      (anonymous function)() at selfEvaluation.jsf:1

      runScripts() at jsf.js.jsf:1

      doUpdate() at jsf.js.jsf:1

      response() at jsf.js.jsf:1

      richfaces.queue.response() at richfaces-queue.js.jsf:407

      jsf.ajax.response() at richfaces-queue.js.jsf:50

      onComplete() at jsf.js.jsf:1

      req.xmlReq.onreadystatechange() at jsf.js.jsf:1

       

      <h:form id="selectorForm">

        ...

         <h:selectOneMenu id="evalYear" value="#{evalBean.evalYear}">

          ...

           <f:ajax event="change" listener="#{evalBean.changeEvalYear}" render=":evalGroup"/>

         </h:selectOneMenu>

      </h:form>

       

      <h:panelGroup id="evalGroup">

        <h:form id="evalForm" prependId="false" rendered="#{!empty evalBean.selfEvaluation}">

          ...

          <rich:tabPanel id="evalTabs" switchType="client">

            <c:forEach items="#{evalBean.categories}" var="category">

              <rich:tab id="tab-#{category.id}" header="#{category.name}"/>

            </c:forEach>

          </rich:tabPanel>

        </h:form>

      </h:panelGroup>

        • 2. Re: Dynamic rich:tabPanel cannot switch tabs
          Scott Balmos Newbie

          I don't think so. The frustrating thing is that a new test page, structurally the same, works. The only difference I can think of is the forEach, where I have #{evalBean.categories}, is really more like #{evalBean.selfEvaluation.template.categories}, where selfEvaluation is a Hibernate entity that is null at the first page load, but then is loaded in the ajax menu onChange listener. I'm trying to do some testing to see if there's any difference there. But it's frustrating that a new page that is effectively the same structure, even in the backing bean, works.

          • 3. Re: Dynamic rich:tabPanel cannot switch tabs
            Scott Balmos Newbie

            I've got it, although I can't really explain it. The issue is because the first time the page is rendered, #{evalBean.selfEvaluation} is null. The selectOneMenu effectively is where you're selecting an evaluation to load. So, the first time the page is rendered, there are no tabs that end up in the tabPanel component tree. Something about that causes *something* to not bind correctly in JSF's jQuery, such that the next time around the page is partially rendered, and the tabPanel renders the tabs, you get the Javascript error.

             

            My "fix" is to force a tab to always be present in the component tree. I added a <rich:tab rendered="false"/> at the top of my tabPanel, before the forEach. This forces a tab to be added to the tree, and fixes whatever is going on with JSF's jQuery. Thus, when the page is partially re-rendered due to the selectOneMenu ajax onChange handler, everything is kosher, and I can now switch between tabs.

             

            If you went back to my test page and code, and made it such that #{evalBean.categories} is initially null, but then is populated with a collection of categories in the changeEvalYear method, for example, you should be able to reproduce the issue.