[jsr-314-open] h:outputScript doesn't work inside composite components

Jim Driscoll Jim.Driscoll at SUN.COM
Mon May 11 13:54:14 EDT 2009


On 5/11/09 9:30 AM, David Geary wrote:
> 2009/5/11 Ryan Lubke <Ryan.Lubke at sun.com <mailto:Ryan.Lubke at sun.com>>
>
>     On 5/11/09 7:40 AM, David Geary wrote:
>
>         I have a login composite component that looks like this:
>
>         <composite:interface>...</composite:interface>
>         ...
>         <composite:implementation>
>         <script type="text/javascript">
>                         function checkForm(form) {
>                           var name = form['#{cc.clientId}:name'].value;
>                           var pwd = form['#{cc.clientId}:password'].value;
>
>                           if (name == "" || pwd == "") {
>                             alert("Please enter name and password.");
>                             return false;
>                           }
>                           return true;
>                         }
>         </script>
>           ...
>         </composite:implementation>
>
>         I have components with "name" and "password" component ids in a
>         form in the ... part of the implementation. That works fine.
>
>         However, if I pull the JS out into its own file, and do this:
>
>         <composite:interface>...</composite:interface>
>         ...
>         <composite:implementation>
>         <h:outputScript library="components/login" name="login.js"/>
>           ...
>         </composite:implementation>
>
>         h:outputScript puts the JS in the page, but the JS no longer
>         works because the expression cc.clientId evaluates to an empty
>         string.
>
>         That's a bug, is it not?
>
>     No, I don't believe it is.  The javascript file will be served in a
>     separate request.  There is no way to determine the
>     component at that time.
>
>
> That's what I figured, but that's not going to be obvious to the average
> developer. This is a pretty serious violation of the principle of least
> astonishment, and JSF has enough of those violations, IMO.
>
> If there's no way to make it work, it should be documented, preferably
> in the pdl (or is it vdl now?) docs that h:outputScript will not work
> when the corresponding JS references a composite component.
>

I agree that we should document how to do this:  Which is why I wrote a 
demo that does this (basic-ezcomp/spinner-final) - and blogged about it 
http://weblogs.java.net/blog/driscoll/archive/2008/11/jsf_20_writing.html

The problem is not solvable the way that you think it is:  I struggled 
with this too, until Ryan walked me through it.  The problem is one of 
the web, not one of the JSF, exactly.

So, look at it this way:  The JavaScript file is served ONCE, from ONE 
known address.  This is good - it allows us to cache the javascript 
file.  This is bad - because we do the # variable substitution *before* 
we serve the file, we can't do #{cc} substitutions in it, that file 
could (and will) be shared across views - and even across different 
websurfing sessions, after all, that's the whole point of the resource 
mechanism...  Efficient use of caching for resources.

So, how to address this?  One way is in the demo - just set the 
cc.clientId as a context, and use that context in the function calls.
In a different demo (ajax-switchlist) I save that context into state, 
and use that in each call.  Either way works, and both require about 
four lines of (javascript) code.

If you make it so that we make those substitutions into the javascript 
file, then you also need to output that javascript file with a view 
unique name.  And that's probably a bad idea for most uses, since that 
shoots caching in the head.  We could add a "perview" attribute to each 
resource, I guess, but since the workaround is so easy, once you know 
it, and the cost is the loss of caching, I'd argue this isn't a good idea.

I urge you to run through the demos I wrote (basic-ajax, basic-ezcomp, 
basic-ajax-edittext, ajax-switchlist)  - they're all small, and in each 
of them, I try to tackle one small problem and solve it.  In many of 
them, I ran into problems just like this, and worked through them. 
They're not documented (except in blogs), but they are all small pieces 
of code.

Jim




More information about the jsr-314-open-mirror mailing list