Thursday, April 14, 2005

Dynamic JavaScript

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


In one of my

recent blogs

I talked about using JavaScript in your page to do client-side textfield
input masking. The JavaScript in that example was completely static - the
JavaScript code itself is entered into the page (or a separate JavaScript
file) and is not affected by anything happening on the server.



But what if you want to modify your JavaScript to use data from some
computation you've performed in your Java code on the server?
That's essentially what

somebody asked on the forum
the other day:


How can my JavaScript reference a field in my Java page bean?



One way to do this would be to use a InputHidden component.
In your Java code, you can set the value of the InputHidden, and then
you can reference this value from JavaScript. Specifically, if you
drop an InputHidden on your page, such that its id is
hiddenField1, then your JSP can look like this:


...
<h:inputHidden binding="#{Page1.hiddenField1}" id="hiddenField1"/>
<script>
document.write("Message = " + document.getElementById("form1:hiddenField1").value);
</script>
...


Obviously, in your Java code on the server you'd do something like this:

...
hiddenField1.setValue("Hello World");
...

If you now run you'll see "Message: Hello World" in the page.



However, there's an even simpler way, using the Output Text component.
Normally, if you set the value of an Output Text component to
Hello <b>World<b> then the component will display
exactly that value to the user. But the Output Text has an "Escape" property
which is normally set to true. This is what is ensuring that the < in
the text is properly escaped to the html entity for the less than sign,
&lt;. You can however turn off the Escape property, and pass
through HTML directly to your page!! If you do that, your output text will
display the rendered HTML instead: "Hello World".



Thus, we can create the JavaScript code itself on the server and
send it to the page by just binding an output text to a property which
returns javascript, and turning off escape.
Or better yet, keep the JavaScript mostly in the JSP and reference the
data within the script string using one or more value binding expressions.
To do this, first create a property in your Page, such as foo,
which returns the data you want to insert into your JavaScript:


public String getFoo() {
return "Hello World";
}


Now drop an Output Text, set it to the following value, and then turn off
its Escape property:



<script>document.write("Message: #{Page1.foo}");</script>



More on this shortly.


4 comments:

  1. Sudhakar ChavaliJuly 10, 2005 at 9:57 PM

    So,
    You mean to say if I want to set the JSP variable to jsp component then I need to do something like this
    document.getElementById("form1:hiddenField1").value=<%=myJspVaraible%>
    is that right?

    ReplyDelete
  2. No, that's not what I meant. First of all, you cannot use the old-style JSP syntax (<% %>) in Creator, you must use the XML format of JSP.
    However, what I meant above is that all you need to do is drop a Hidden Input component on your page, and then in your Java code (such as in the beforeRenderResponse, or in Creator 2, "prerender"), call something like inputHidden1.setValue(yourOwnCodeHere());. Now JavaScript in the page can reference this server-side computed value by simply referencing it as shown in the JavaScript above.

    ReplyDelete
  3. David Piersol-FreedmanMay 4, 2006 at 11:01 AM

    So what about something like this? I need to dynamically assign a value to a javascript array like this:
    <ui:script binding="#{appStartSaa.script3}" id="script3">
    var repList = new Array(#{RepListBuilder.repList})
    </ui:script>
    But this gets rendered in the browser as:
    <script id="script3" type="text/javascript">
    var repList = new Array(#{RepListBuilder.repList})
    </script>
    Is there a way to do this?

    ReplyDelete