JSF 2 custom composite component with f:ajax

ajax, composite-component, custom-component, event-handling, jsf-2

Solution

The `<f:ajax>` can only be attached to a `ClientBehaviorHolder` such as `<h:inputText>`. A plain HTML `<div>` isn't such one component. You basically need to have a HTML `<input>` element, not a `<div>` element. Even more, how would you otherwise set the submitted value in the bean?

<cc:interface>
    ...
    <cc:clientBehavior name="customEvent" targets="input" event="valueChange" />
</cc:interface>
<cc:implementation>
    ...    
    <h:inputText id="input" value="#{cc.attrs.value}" />

    <h:outputScript>
        jQuery("[id='#{cc.clientId}:input']").ColorPicker({ 
            // ...
        });
    </h:outputScript>
</cc:implementation>

(please note that I fixed the jQuery selector as well; this way the JSF client ID separator `:` will be taken into account properly instead of malforming the CSS selector)

Unrelated to the concrete problem, your usage of `<f:ajax onevent>` is wrong. It should point to a function reference, it should not contain some function calls. The proper usage is

<f:ajax ... onevent="functionName" />

...

<h:outputScript>
    function functionName(data) {
        alert("Event " + data.status + " raised");
    }
</h:outputScript>

See also:

- ajax call in jsf 2.0 (myfaces), the onevent Javascript function in the ajax tag gets called before the rendering is complete

Problem

I'm trying to create a custom composite component colorPicker using this jQuery plugin http://www.eyecon.ro/colorpicker/. I´d like to be able to append a jsf tag `f:ajax`, and when a color is selected, perform an ajax call to the server. I have been testing this functionality and it all appears to be right, but obviously I missed something, because the listener is never called. This is my component code: ``` <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:composite="http://java.sun.com/jsf/composite"> <composite:interface> <composite:attribute name="label" /> <composite:clientBehavior name="customEvent" event="change" targets="#{cc.clientId}"/> </composite:interface> <composite:implementation> <h:outputStylesheet library="css" name="colorpicker/colorpicker.css" /> <h:outputStylesheet library="css" name="colorpicker/layout.css" /> <h:outputScript library="js" name="colorpicker/jquery.js" target="head"/> <h:outputScript library="js" name="colorpicker/colorpicker.js" target="head"/> <h:outputScript library="js" name="colorpicker/eye.js" target="head"/> <h:outputScript library="js" name="colorpicker/utils.js" target="head"/> <h:outputScript library="js" name="colorpicker/layout.js" target="head"/> <h:outputScript library="js" name="colorpicker/hex.js" target="head"/> <div id="#{cc.clientId}" class="colorSelector"> <div style="background-color: #0000FF;"></div> </div> <script> //jQuery(document).ready(function() { jQuery('##{cc.clientId}').ColorPicker({ color: '#0000ff', onShow: function (colpkr) { jQuery(colpkr).fadeIn(2000); alert('onchange1'); launchEvent(document.getElementById('#{cc.clientId}')); alert('onchange2'); //return false; }, onHide: function (colpkr) { jQuery(colpkr).fadeOut(2000); return false; }, onChange: function (hsb, hex, rgb) { } }); //}); /* <![CDATA[ */ function launchEvent(fieldName) { alert('launchEvent1'); if ("fireEvent" in fieldName) { alert('launchEvent2'); fieldName.fireEvent("onchange"); alert('launchEvent3'); } else { alert('launchEvent4'); var evt = document.createEvent("HTMLEvents"); alert('launchEvent5'); evt.initEvent("change", false, true); alert('launchEvent6'); fieldName.dispatchEvent(evt); alert('launchEvent7'); } /* ]]> */ } </script> </composite:implementation> </html> ``` And this is the page implementation: ``` <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:r="http://richfaces.org/rich" xmlns:a="http://richfaces.org/a4j" xmlns:s="http://jboss.org/seam/faces" xmlns:cp="http://java.sun.com/jsf/composite/component"> <h:head> <title>Test</title> </h:head> <h:body> <f:view> <h:form prependId="false"> <cp:colorpicker id="colorSelector"> <f:ajax event="customEvent" listener="#{themeBean.changeColor1}" onevent="alert('event raised');"/> </cp:colorpicker> <h:inputText value="#{themeBean.color1}"></h:inputText> </h:form> </f:view> </h:body> </html> ```

Original source

Related problems