Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RichFaces tabPanel with switchType ajax and a4j:status

What I try to achieve

I've got a rich:tabPanel with switchType="client" and one of the tabs has set its switchType to ajax because loading its data is an expensive operation. When I click on this Ajax Tab I want its title to be changed to Loading... to indicate that the click has been recognized. When it has finished loading, the title should switch back to Ajax Tab.

[Client Tab] [Ajax Tab]
<click on 'Ajax Tab'>
[Client Tab] [Loading...]
<wait...>
[Client Tab] [Ajax Tab]
<click on 'Client Tab'>
[Client Tab] [Ajax Tab]

Problem description

Actually, most of the described above works as expected, the only problem I have is, that when I navigate from the Ajax Tab to any other tab, the title of the Ajax Tab switches back to Loading...:

[Client Tab] [Ajax Tab]
<click on 'Ajax Tab'>
[Client Tab] [Loading...]
<wait...>
[Client Tab] [Ajax Tab]
<click on 'Client Tab'>
[Client Tab] [Loading...]

Research

I've found an issue in RichFaces' JIRA but this issue is fixed since version 3.2.1. Furthermore I've googled for a few hours but wasn't able to find any similar problems.

Environment

  • Tomcat 7.0.30
  • Mojarra 2.1.12
  • RichFaces 4.2.2.Final

Code (reduced)

JSF

<ui:composition template="WEB-INF/templates/default.xhtml">
    <ui:define name="content">
        <h:form id="form">
            <rich:tabPanel id="tabPanel" switchType="client">
                <rich:tab id="clientTab">
                    <f:facet name="header">
                        <h:outputText value="Client Tab" />
                    </f:facet>
                    <h:outputText value="Foo" />
                </rich:tab>
                <rich:tab id="ajaxTab" switchType="ajax" status="ajaxTabStatus">
                    <f:facet name="header">
                        <a4j:status id="ajaxTabStatus">
                            <f:facet name="start">
                                <h:outputText value="Loading..." />
                            </f:facet>
                            <f:facet name="stop">
                                <h:outputText value="Ajax Tab" />
                            </f:facet>
                        </a4j:status>
                    </f:facet>
                    <h:outputText value="#{bean.value}" />
                </rich:tab>
            </rich:tabPanel>
        </h:form>
    </ui:define>
</ui:composition>

Backing Bean of Ajax Tab

@ManagedBean
@ViewScoped
public class Bean implements Serializable {

    private static final long serialVersionUID = -8405248908693334970L;

    private String value = "noValue";

    private static final Logger log = LoggerFactory.getLogger(Bean.class);

    @PostConstruct
    public void init() {
        log.info("Init bean.");
        value = getDummyValueWithFakeDelay();
    }

    public String getValue() {
        log.info("Get value.");
        return value;
    }

    private String getDummyValueWithFakeDelay() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
        }

        return DateFormat.getTimeInstance().format(new Date());
    }
}

Update 1:

I've found out that the identifier (i mean that one you specify like <rich:someTag ... status="someStatus" />) of an a4j:status is not its id but its name attribute. So my a4j:status is just for every Ajax request on that page. Giving it a name and using this named status does not work though, because nothing at all happens now.

<rich:tab id="ajaxTab" switchType="ajax" status="ajaxTabStatus">
    <f:facet name="header">
        <a4j:status id="ajaxTabStatus" name="ajaxTabStatus">
            <f:facet name="start">
                <h:outputText value="Loading..." />
            </f:facet>
            <f:facet name="stop">
                <h:outputText value="Ajax Tab" />
            </f:facet>
        </a4j:status>
    </f:facet>
    <h:outputText value="#{bean.value}" />
</rich:tab>

Update 2:

I've also found another approach, using onbegin and oncomplete attributes with some code like:

<rich:tab id="ajaxTab" switchType="ajax"
    onbegin="#{rich:component('ajaxTab')}.?"
    oncomplete="#{rich:component('ajaxTab')}.?">

Well, as you see, I haven't found a way to manipulate the tab title yet (and I didn't find any useful documentation of what I can do with a rich:component).

like image 314
Markus Ratzer Avatar asked Oct 01 '12 13:10

Markus Ratzer


2 Answers

I am not very much familiar with RichFaces 4.x. However this is how to do it in RichFaces 3.
Assume this as you tabPanel.

<h:form>
  <rich:tabPanel>
    <rich:tab label="Client Tab" switchType="client">
      Tab - client
    </rich:tab>

    <rich:tab label="Ajax Tab" id="ajaxTab" switchType="ajax" ontabenter="changeLabel(event)">
      <h:outputText value="#{bean.value}" />
    </rich:tab>
  </rich:tabPanel>
</h:form>

Note the ontabenter event in the ajax tab.

Now your scripts would be like this.

<script>
    function changeLabel(tabId) {
        var tabLabel = event.target || event.srcElement;
        tabLabel.innerHTML = 'Loading...';
    }
</script>

I don't know much about RF4. However in RF3 it is not needed to add an oncomplete event to the tab.

like image 53
prageeth Avatar answered Nov 18 '22 10:11

prageeth


I do the code below with richfaces 4.3.7. It seem to work. (I display loading panel instead of modify tab header.)

<a4j:status oncomplete="#{rich:component('busy')}.hide()"
    onerror="#{rich:component('busy')}.hide()"
    onbegin="#{rich:component('busy')}.show()">
    <rich:popupPanel id="busy" modal="true" moveable="false"
        resizeable="false" autosized="true">
        <h:panelGrid styleClass="alignCenter" width="100%" id="busyPanel"
            columns="1" border="0" cellpadding="0" cellspacing="2">
            <h:outputLabel value="Loading..." />
        </h:panelGrid>
    </rich:popupPanel>
</a4j:status>
<h:form>
    <rich:tabPanel switchType="ajax" 
        oncomplete="#{rich:component('busy')}.hide()" 
        onerror="#{rich:component('busy')}.hide()"
        onbegin="#{rich:component('busy')}.show()"
        >
        <rich:tab label="Client Tab" switchType="client">
          Tab - client
        </rich:tab>

        <rich:tab label="Ajax Tab" id="ajaxTab" >
          <h:outputText value="#{bean.value}" />
        </rich:tab>
    </rich:tabPanel>
</h:form>
like image 29
Vu cuong Avatar answered Nov 18 '22 10:11

Vu cuong