Question

i have problem to use widgetVar while its name is generated dynamicly. How properly we can call such widget ? Code of component:

<cc:attribute name="id" required="true" type="java.lang.String" />
...
<cc:implementation>
    <p:selectOneRadio widgetVar="widgetVariable#{cc.attrs.id}" id="#{cc.attrs.id}" required="false" immediate="#{cc.attrs.immediate}"
                      value="#{cc.attrs.value}">
        <p:ajax event="click" oncomplete="checkRadio()"/>
        <cc:insertChildren/>
    </p:selectOneRadio>

    <script type="text/javascript">
        /*  <![CDATA[ */

        function checkRadio() {
            var widgetVariable = widgetVariable#{cc.attrs.id}; //HERE PROBLEM
            widgetVariable.dosmth();
        }

        /*    ]]> */
    </script>
</cc:implementation>  

thats what is wird that it works, but when i uses many istance of this component on page widgetwar sometimes get crazy and make javascript for many istance of component.

Edit: everything works fine. Anyway i have one new problem. I created in this .js file some global state variable.

var state = -1;

function checkRadio() {
        var widgetVariable = widgetVariable#{cc.attrs.id}; //HERE PROBLEM
        widgetVariable.dosmth(state);
}

But each state should be only for one composite istance, atm every composite use this var, some ideas?

Was it helpful?

Solution

There are actually 2 problems.

The first problem is that you're declaring JS functions in a XHTML file instead of a real JS file. If you've multiple of those components, then you're basically generating multiple JS functions checkRadio() to the HTML output. Pull the page in your browser, rightclick and View Source. You'll basically see

<script type="text/javascript">
    function checkRadio() {
        // ...
    }
</script>
<script type="text/javascript">
    function checkRadio() {
        // ...
    }
</script>
<script type="text/javascript">
    function checkRadio() {
        // ...
    }
</script>
...

They're overriding each other until the last one. So when checkRadio() is called, actually the last one will be invoked. This obviously isn't right.

You should have only one function. You can externalize the variable by simply making it a function argument. Even more, you should not be writing JS code in a XHTML file, but in a standalone JS file which you include by <h:outputScript>. Additional bonus, it will automatically make sure that there's only one JS file loaded even though you've multiple composite components.

<cc:implementation>
    <h:outputScript name="myComposite.js" />
    ...
    <p:ajax event="click" oncomplete="checkRadio('#{cc.attrs.id}')" />
</cc:implementation>

Coming back to your concrete question, your second problem, you can make use of window[variableName] notation to get a hand of a global (window) variable by a dynamically composed variable name. So, the checkRadio() function in your myComposite.js (name it whatever you want, but the same filename as myComposite.xhtml would be most self-documenting) should look like this:

function checkRadio(compositeId) {
   var widgetVariableName = "widgetVariable" + compositeId;
   var widgetVariable = window[widgetVariableName];
   widgetVariable.dosmth();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top