Including JSF Expression Language in JavaScript

2019-07-07 02:18发布

I found this question and answer Mixing JSF EL in a JavaScript file

The question was asked over 2 years ago so was wondering if there are any further alternatives with JSF 2.0.

I've been looking at using

<h:outputStylesheet> 

for including CSS and this EL in these files does seem to get parsed.

However using

<h:outputScript>

doesn't seem to do the same.

So

Question 1) Would the above be the better way of doing it (if it worked)?

Question 2) As it doesn't seem to work with JS, which of the answer in Mixing JSF EL in a JavaScript file post is considered the better option.

Thanks

2条回答
不美不萌又怎样
2楼-- · 2019-07-07 02:42

Currently, there's no way through the JSF API to add JS to EL-supported resources. In case of Mojarra, it's hardcoded in the com.sun.faces.application.resource.ResourceHelper class.

private static final String[] EL_CONTENT_TYPES = {
    "text/css"
};

There is no way to override this by wrapping one of the resource management components. EL is supported in CSS with the sole purpose to support "static" #{resource['library:image.png']} expressions in CSS background image declarations. With "static", I mean, that they guarantee the same evaluated result applicationwide. Other use cases, also for JS, are not been considered in the JSF specification. EL expressions which may evaluate a different result on a per-request basis would fail in a JS/CSS resource because the webbrowser by default caches those resources for a determined time after the first request, which may last up to at least one week.

You can always get it to work by implementing a custom resource handler wherein you pull the JS file through an EL evaluating input stream and set the appropriate response headers so that the browser won't cache them. But this is not exactly a trivial job because you basically need to rewrite the entire resource management system. If you really intend to and are experienced enough, then the starting point would be extending the ResourceHandlerWrapper class. The remnant should speak for itself then.

As to which of the mentioned alternatives is a better option, is a choice you've to make yourself. Outweigh yourself how more or less useful the one or the other approach is for your particular case.

查看更多
你好瞎i
3楼-- · 2019-07-07 02:44

I'd add to the list of options BalusC offered a variation on the first one that'd avoid a global variable:

<script id='message-data' type='text/json'>
  { "messages": [    
  <ui:repeat items="#{bean.messages}" var="message">"#{message.value}",</ui:repeat> null
  ] }
</script>

Then from JavaScript, when you need the messages you can:

var msgData = document.getElementById('message-data').innerHTML;
msgData = JSON.parse(msgData);

The idea is to create a JSON object in an unparsed <script> tag (that's what setting the "type" to "text/json" will do) and then read it via JSON.parse.

Another (general) approach is to use classes and data-xxx attributes to drop things from the JSF context into the HTML, which can then be "discovered" by JavaScript.

Using the server-side templating system to process whole JavaScript files has the significant disadvantage of making those files non-cacheable by clients.

查看更多
登录 后发表回答