1

My goal is to pass a string with parameters (Hello {0}) from the backing bean to JavaScript. My current approach is to put the string in a h:inputHidden and let JS read the value onLoad. Sadly f:param inside of h:inputHidden is not working as in a h:outputFormat.

What approach is generally advisible?

  • I could combine the string with the parameters in the backing bean, but imo that should not be that beans concern.
  • I could combine them in JS, but again that seems like reinventing the wheel (using replace functions ...)
  • I dont see a (good) way to use a h:outputFormat but make it invisible to the user.
  • I see no way to make h:inputHidden accept f:params.

EDIT: The actual implementation used is Apache MyFaces 1.1.4, so I updated the title to JSF 1.1.

Due to BalusCs answer I remembered my first (and discarded) approach:

  • Direct inclusion in JS source code.

    <script>
        var text = '<h:outputFormat value="Hello {0}"><f:param value="World" /></h:outputFormat>';
    </script>
    

Sadly in JSF 1.1 I have to use <f:verbatim> which makes the code really ugly (even eclipses syntax checker doesnt understand it - although its working):

<f:verbatim>
    <script>
        var text = '</f:verbatim>
<h:outputFormat value="Hello {0}"><f:param value="World" /></h:outputFormat>
<f:verbatim>';
        </script>
</f:verbatim>

And an additional drawback is that I cannot put that in the <head> since it has to be inside <f:view>.

SebastianH
  • 2,172
  • 1
  • 18
  • 29
  • @BalusC, @LaurentG: Thank you both for your comments. I will accept LautentGs answer because it is also my preferred approach. As mentioned in my question edits the `` approach is really ugly. I will award the bounty to BalusC though because of all the time he spent on his answers and comments that helped me alot :) – SebastianH Feb 14 '14 at 13:04
  • Thank you. I'd have loved to receive my first bounty, but I must agree, balusC's answers are always the best! – LaurentG Feb 14 '14 at 14:56

2 Answers2

3

JSF is in the context of this question merely a HTML/JS code generator. You don't actually pass anything from JSF to HTML/JS. You actually just let JSF in the webserver print the desired HTML/JS code so that the webbrowser can in turn properly execute it.

So, all you need to do is to just write JSF code in such way that it prints exactly the desired JS code.

<script>
    var text = '<h:outputFormat value="Hello {0}"><f:param value="World" /></h:outputFormat>';
</script>

When opening the JSF page in browser (in other words, when sending a HTTP request to the server which invokes the FacesServlet which in turn does all the JSF work of generating the HTML/JS), and doing a rightclick and View Source, you should see something like this:

<script>
    var text = 'Hello World';
</script>

Your JS code which is executed hereafter should be able to grab this value by variable name text.

Be however careful with special characters such as newlines. You may need to create a custom EL function which delegates to Apache Commons Lang StringEscapeUtils#escapeJavaScript(), see also How to escape JavaScript in JSP?


Update: as per the comments you seem to be using JSF 1.1. If upgrading is not an option (I however strongly recommend to do so; practically any JSF 1.1 project is without code changes forwards compatible with JSF 1.2), then you need to put the non-JSF markup in <f:verbatim> "the usual way".

<f:verbatim><script>
    var text = '</f:verbatim><h:outputFormat value="Hello {0}"><f:param value="World" /></h:outputFormat><f:verbatim>';
</script></f:verbatim>

See also among others Why Facelets is preferred over JSP as the view definition language from JSF2.0 onwards? and JSF/Facelets: why is it not a good idea to mix JSF/Facelets with HTML tags? for some background information.

As per your complaint,

And an additional drawback is that I cannot put that in the <head> since it has to be inside <f:view>.

this is absolutely not true. Definitely you can put this in <head>. Just move the <f:view> from inside <body> to outside the <body>, wrapping both <head> and <body> or even <html>.

<%@page pageEncoding="UTF-8"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<!DOCTYPE html>
<html lang="en">
    <f:view>
        <head>...</head>
        <body>...</body>
    </f:view>
</html>
Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks for your answer. That was actually the first approach I tried, but forgot to mention it in my question here. My problem with it is, that it just wouldnt work for me. Whereever I put your code snippet, the HTML source shows: `var text = '';` (I tried in the and in the inside a ). I am new to JSF and looking into an existing complex project, so I cannot yet say if further configuration is required. – SebastianH Feb 12 '14 at 11:05
  • Works for me. Your problem is caused elsewhere not visible in the information provided so far. Hard to answer as long as you don't elaborate "wouldnt work" in developer's perspective instead of enduser's perspective. – BalusC Feb 12 '14 at 11:06
  • Sorry, my comment wasnt done yet. I always fall for (`SHIFT`) `ENTER` in the comment box :( – SebastianH Feb 12 '14 at 11:09
  • Which JSF impl/version are you using? Did you use the test code exactly as in my answer or did you substitute the `value` with a bean property or bundle variable? – BalusC Feb 12 '14 at 11:17
  • I [found out](http://stackoverflow.com/questions/13125782/how-to-detect-current-jsf-version) that **Apache MyFaces 1.1.4** is used. I fear this implies that actually JSF 1.1 is used? I might have to update the question. I copied your code _as is_ and didnt change the EL so no reference to any bean is used. – SebastianH Feb 12 '14 at 11:34
  • Yup, that's a JSF 1.1 implementation. However, code should theoretically work as good for JSF 1.1. You only need to put `` around non-JSF markup "the usual way" (or, better, upgrade to JSF 1.2 so that you don't need the `` mess anymore; JSF 1.1 projects are generally without any necessary code changes forwards compatible with JSF 1.2). – BalusC Feb 12 '14 at 11:41
1

Since you are using JSF 1.2, I would use your third solution:

XHTML:

<body onLoad="doOnLoad();">
    <h:outputFormat id="myString" value="Hello {0}" styleClass="hidden">
        <f:param value="World" />
    </h:outputFormat>

JavaScript:

function doOnLoad() {
    // do something with the String
    alert(document.getElementById('myString').innerHTML);
}

CSS:

.hidden {
    display:none;
}

References

Community
  • 1
  • 1
LaurentG
  • 11,128
  • 9
  • 51
  • 66