Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
143 views
in Technique[技术] by (71.8m points)

How can I know the id of a JSF component so I can use in Javascript

Problem: Sometimes you will want to access a component from javascript with getElementById, but id's are generated dynamically in JSF, so you need a method of getting an objects id. I answer below on how you can do this.


Original Question: I want to use some code like below. How can I reference the inputText JSF component in my Javascript?

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <head>
       <title>Input Name Page</title>
        <script type="javascript" >
          function myFunc() {
            // how can I get the contents of the inputText component below          
            alert("Your email address is: " + document.getElementById("emailAddress").value);
          }
       </script>
    </head>
    <h:body>
        <f:view>
            <h:form>
                Please enter your email address:<br/>
                <h:inputText id="emailAddresses" value="#{emailAddresses.emailAddressesStr}"/>
                <h:commandButton onclick="myFunc()" action="results" value="Next"/>
            </h:form>
        </f:view>
    </h:body>
</html>

Update: this post Client Identifiers in JSF2.0 discusses using a technique like:

<script type="javascript" >
  function myFunc() {
    alert("Your email address is: " + document.getElementById("#{myInptTxtId.clientId}").value);
  }
</script>

<h:inputText id="myInptTxtId" value="backingBean.emailAddress"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>

Suggesting that the attribute id on the inputText component creates an object that can be accessed with EL using #{myInptTxtId}, in the above example. The article goes on to state that JSF 2.0 adds the zero-argument getClientId() method to the UIComponent class. Thereby allowing the #{myInptTxtId.clientId} construct suggested above to get the actual generated id of the component.

Though in my tests this doesn't work. Can anyone else confirm/deny. The answers suggested below suffer from drawback that the above technique doesn't. So it would be good to know if the above technique actually works.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You need to use exactly the ID as JSF has assigned in the generated HTML output. Rightclick the page in your webbrowser and choose View Source. That's exactly the HTML code which JS sees (you know, JS runs in webbrowser and intercepts on HTML DOM tree).

Given a

<h:form>
    <h:inputText id="emailAddresses" ... />

It'll look something like this:

<form id="j_id0">
    <input type="text" id="j_id0:emailAddress" ... />

Where j_id0 is the generated ID of the generated HTML <form> element.

You'd rather give all JSF NamingContainer components a fixed id so that JSF don't autogenerate them. The <h:form> is one of them.

<h:form id="formId">
    <h:inputText id="emailAddresses" value="#{emailAddresses.emailAddressesStr}"/>

This way the form won't get an autogenerated ID like j_id0 and the input field will get a fixed ID of formId:emailAddress. You can then just reference it as such in JS.

var input = document.getElementById('formId:emailAddress');

From that point on you can continue using JS code as usual. E.g. getting value via input.value.

See also:


Update as per your update: you misunderstood the blog article. The special #{component} reference refers to the current component where the EL expression is been evaluated and this works only inside any of the attributes of the component itself. Whatever you want can also be achieved as follows:

var input = document.getElementById('#{emailAddress.clientId}');

with (note the binding to the view, you should absolutely not bind it to a bean)

<h:inputText binding="#{emailAddress}" />

but that's plain ugly. Better use the following approach wherein you pass the generated HTML DOM element as JavaScript this reference to the function

<h:inputText onclick="show(this)" />

with

function show(input) {
    alert(input.value);
}

If you're using jQuery, you can even go a step further by abstracting them using a style class as marker interface

<h:inputText styleClass="someMarkerClass" />

with

$(document).on("click", ".someMarkerClass", function() {
    var $input = $(this);
    alert($input.val());
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...