Search code examples
javajsfnavigationrichfacescomposite-component

Unable to find matching navigation case from composite component


I have a composite component button and the action is coming from an attribute.

<comp:interface>
    <comp:attribute name="buttonId" required="false"/>
    <comp:attribute name="action" required="false" method-signature="java.lang.String action()"/>
    <comp:attribute name="alt"/>
    <comp:attribute name="value" />
    <comp:attribute name="immediate"/>
</comp:interface>

<comp:implementation>
    <h:commandButton alt="#{cc.attrs.alt}" action="#{cc.attrs.action}"
                     value="#{cc.attrs.value}"  id="#{cc.attrs.buttonId}"
                     immediate="#{cc.attrs.immediate}"/>
</comp:implementation>

When I create the button the action comes from my controller.

<test:myButton value="Test" alt="test" action="{myController.doSomething}" immediate="true" buttonId="testId"/> 

I then have a navigation rule that looks for myController.doSomething

<navigation-case>
        <from-action>#{myController.doSomething}</from-action>
        <from-outcome>success</from-outcome>
        <to-view-id>/pages/test1.xhtml</to-view-id>
        <redirect />
 </navigation-case>

The problem is when I click on the button the action is coming from #{cc.attrs.action} so I get the following error

Unable to find matching navigation case with from-view-id '/pages/test.xhtml' for action '#{cc.attrs.action}' with outcome 'success'

How can I get around this?


Solution

  • Adding the targets attribute to re-target the action attribute to the commandButton will resolve the issue. The action attribute is then not necessary on the commandButton.

    <comp:interface>
        <comp:attribute name="buttonId"/>
        <comp:attribute name="action" targets="#{cc.attrs.buttonId}" method-signature="java.lang.String action()"/>
        <comp:attribute name="alt"/>
        <comp:attribute name="value" />
        <comp:attribute name="immediate"/>
    </comp:interface>
    
    <comp:implementation>
        <h:commandButton alt="#{cc.attrs.alt}" 
                         value="#{cc.attrs.value}"  id="#{cc.attrs.buttonId}"
                         immediate="#{cc.attrs.immediate}"/>
    </comp:implementation>
    

    http://www.devmanuals.com/tutorials/java/jsf/jsf2TagLibrary/composite/attribute.html

    targets : This is a required attribute that specifies the target to invoke the component client ids of by the 'method-signature' attribute (if present). Different target client ids can be separated by a space (not tab space) in target list but, if this attribute is not used with this tag and the attribute method-signature is used then only the value of 'name' attribute is targeted or can say the only value of 'name' attribute is targeted.

    You can also use the method described under the targetAttributeName attribute documentation from the link below. Basically you would have the name of the cc:attribute be the same as the commandButton id and then use targetAttributeName="action" to say that you are re-targeting for the commandButton action attribute.

    http://docs.oracle.com/javaee/6/javaserverfaces/2.1/docs/vdldocs/facelets/composite/attribute.html