Integrate JavaScript in JSF composite component, the clean way
Asked Answered
L

1

9

In JSF, what would be the "right" and "clean" way to integrate JavaScript i.e. into a composite-compenent? I am a fan of Unobtrusive JavaScript, and separating HTML from JS from CSS. What would be a good way to have as little quirks as possible? This is what I like the best so far:

<composite:interface>
  // ...
</composite:interface>

<composite:implementation>
  // ...
  <script> initSomething('#{cc.clientId}'); </script>
</composite:implementation>    

What I don't like is, to use language A to generate language B. Basically the same goes for event handlers and stuff. My favorite would be to attach those handlers via <insert favorite DOM JavaScript library here>. Is this possible? How do you do this kind of integration?

Lantana answered 27/9, 2012 at 6:41 Comment(2)
I'm not sure if I understand your concrete problem/question. You can just use for example jQuery. Popular JSF component libraries such as PrimeFaces and RichFaces also use jQuery under the covers.Cassondracassoulet
Yes, of course. But somehow I have to retrieve a reference to that DOM element. Using an ID would be the only way to make sure it is unique (thats what an ID is for, after all). Now I don't want to generate some piece of JavaScript, but how do I get a DOM node then?Malebranche
C
9

I'd say that what you've there is the best you can get, provided that you're absolutely positive that the HTML element's nature is so unique that you absolutely need to select it by an ID, every time again.

If the HTML representation is not that unique (I can imagine that a Facelets template or include file might contain application-wide unique HTML elements like header, menu, footer, etc, but a composite component which can be reused multiple times in a single view? I can't for life imagine that), then you could also consider using an unique classname and hook initialization on it.

E.g. /resources/composites/yourComposite.xhtml

<cc:implementation>
    <h:outputScript library="composites" name="yourComposite.js" target="head" />
    <div id="#{cc.clientId}" class="your-composite">
        ...
    </div>
</cc:implementation>

with in the /resources/composites/yourComposite.js (assuming that you're using jQuery)

var $yourComposites = $(".your-composite");
// ...

You can if necessary extract the autogenerated HTML element ID for each of them in a jQuery.each():

$yourComposites.each(function(index, yourComposite) {
    var id = yourComposite.id;
    // ...
});
Cassondracassoulet answered 27/9, 2012 at 17:53 Comment(1)
Thanks for your the input. You are right, most parts won't be unique and it doesn't even matter if they are (i.e. header, menu, footer). But my headache starts, when I reload or insert components via AJAX. I can't, and don't want, to reinitialize every component having a certain classname. The simple alternatives would be a unique id, or setting some flag to remember which components were initialized before. The latter requires some code, feels dirty, not really safe and adds some overhead. How did you solve this kind of problem?Malebranche

© 2022 - 2024 — McMap. All rights reserved.