0

I'm trying to render a composite component that shows a popup panel based on the outcome of a backing bean method. So far no success. Would appreciate some help.

  • GlassFish 4.1
  • Mojarra 2.2
  • RichFaces 4.5.4

Composite Component (conditionalActionLink.xhtml):

<ui:component
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:composite="http://java.sun.com/jsf/composite">

<composite:interface>
    <composite:attribute name="value"/>
    <composite:attribute name="style"/>
    <composite:attribute name="disabled"/>
    <composite:attribute name="render"/>
    <composite:attribute name="message" />
    <composite:attribute name="renderedBtn" type="java.lang.Boolean"/>
    <composite:attribute name="condition" required="true" method-signature="java.lang.Boolean action()"/>
    <composite:attribute name="execAction" required="true" method-signature="void action()"/>
</composite:interface>
<composite:implementation>
    <ui:debug hotkey="x" />
    <h:form>
        <a4j:commandLink id="actnlnx" value="#{cc.attrs.value}" oncomplete="#{managePurchases.billHasPaymentsApplied ? showMessage() : submitToServer() }" style="#{cc.attrs.style}" disabled="#{cc.attrs.disabled}"/>
        <a4j:jsFunction name="showMessage" onbegin="#{rich:component('noticeDialog')}.show()" execute="@form"/>
        <a4j:jsFunction name="submitToServer" action="#{cc.attrs.execAction}" render="#{cc.attrs.render}" execute="@form"/>             

        <rich:popupPanel id="noticeDialog" modal="true" autosized="true" resizeable="false" style="FONT-SIZE: large;">
            <f:facet name="header" style="FONT-SIZE: large;">
                <h:outputText value="Notice" />
            </f:facet>
            <f:facet name="controls">
                <h:outputLink value="#" onclick="#{rich:component('noticeDialog')}.hide(); return false;">
                    X
                </h:outputLink>
            </f:facet>
            <h:outputText value="#{cc.attrs.message}"/>
            <br/><br/>
            <h:commandButton value="Ok" onclick="#{rich:component('noticeDialog')}.hide(); return false;" style="FONT-SIZE: large;"/>
        </rich:popupPanel>  
    </h:form>
</composite:implementation>

Invoking page:

<cc:conditionalActionLink value="Delete" style="FONT-SIZE: large;text-decoration:none" message="This bill has payments applied. Please delete payments first." condition="#{managePurchases.billHasPaymentsApplied}" execAction="#{managePurchases.deleteBill}"/>

Btw, I need to use the condition value in the composite component, but challenged with how to avoid nested EL expression: oncomplete="#{cc.attr.condition ? showMessage() : submitToServer() }"

Backing Bean:

public Boolean getBillHasPaymentsApplied(){
    applogger.entry();
    //if(bill.getPayments().size() > 0)
        return applogger.exit(true);
    //else
        //return applogger.exit(false);
}

public void deleteBill(){
    applogger.entry();

    applogger.debug("DELETE BILL HERE.");
    //billDaoBean.deleteBill(bill);

    applogger.exit();

}

I've tried many tweaks, with much search online. With this particular version, error message is

javax.el.ELException: Function 'showMessage' not found

I am seeking a way to achieve this behavior.

Thanks for your help in advance!

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
scorpion
  • 3
  • 3

1 Answers1

1

The oncomplete attribute of the <a4j:commandLink> component must evaluate to a String. Here, your EL tries to invoke either a showMessage() or a submitToServer() java method depending on a boolean value, which are not found.

what you want is a String with the JS function name, so just put function names between single quotes to make them String:

oncomplete="#{managePurchases.billHasPaymentsApplied ? 'showMessage()' : 'submitToServer()'}"

I dont have any RichFaces-ready playground (by the way, never used RichFaces either), so I can't test, but it should do the trick !

Zim
  • 1,457
  • 1
  • 10
  • 21
  • Thanks a lot! That fixed that part of the issue. Now I need to be able to access the backing bean property not by hard coding the property ("managePurchases.billHasPaymentsApplied"), but by passing in the property to be evaluated, as an attribute of the composite component. Note that the ternary operator wants a boolean, not a bean method. I can't evaluate it outside of the cc and pass in a boolean because I use a f:setPropertyActionListener (not shown in code here) to set a backing bean property that is part of the evaluation. – scorpion Jun 14 '15 at 12:16
  • Can you add the `f:setPropertyActionListener` part in your question for clarification? – Zim Jun 14 '15 at 14:31
  • Thanks again. I've resolved the last issue I was having. Had to do with this form issue[link](http://balusc.blogspot.com/2011/09/communication-in-jsf-20.html#AjaxRenderingOfContentWhichContainsAnotherForm). – scorpion Jun 14 '15 at 16:10
  • Glad it's working now! Concerning your question in your edit suggestion (_It works fine, only that it calls #{customerAccounts.billHasPaymentsApplied} 4 times when composite component is in a datatable with 4 of them??_), it's an expected behaviour. Getters are called multiple times in JSF, so don't do any costly logic in them! See [this](http://stackoverflow.com/questions/2090033/why-jsf-calls-getters-multiple-times) – Zim Jun 14 '15 at 16:42