How to trigger click event on command button in JSF, after the evalution of action EL expression [duplicate] - jsf

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.

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:
How to select JSF components using jQuery?
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());
});

Answer: So this is the technique I'm happiest with. Doesn't require doing too much weird stuff to figure out the id of a component. Remember the whole point of this is so you can know the id of a component from anywhere on your page, not just from the actual component itself. This is key. I press a button, launch javascript function, and it should be able to access any other component, not just the one that launched it.
This solution doesn't require any 'right-click' and see what the id is. That type of solution is brittle, as the id is dynamically generated and if I change the page I'll have to go through that nonsense each time.
Bind the component to a backing bean.
Reference the bound component wherever you want.
So here is a sample of how that can be done.
Assumptions: I have an *.xhtml page (could be *.jsp) and I have defined a backing bean. I'm also using JSF 2.0.
*.xhtml page
<script>
function myFunc() {
var inputText = document.getElementById("#{backBean.emailAddyInputText.clientId}")
alert("The email address is: " + inputText.value );
}
</script>
<h:inputText binding="#{backBean.emailAddyInputText}"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>
BackBean.java
UIInput emailAddyInputText;
Make sure to create your getter/setter for this property too.

Id is dynamically generated, so you should define names for all parent elements to avoid j_id123-like ids.
Note that if you use jQuery to select element - than you should use double slash before colon:
jQuery("my-form-id\\:my-text-input-block\\:my-input-id")
instead of:
jQuery("my-form-id:my-text-input-block:my-input-id")
In case of Richfaces you can use el expression on jsf page:
#{rich:element('native-jsf-input-id')}
to select javascript element, for example:
#{rich:element('native-jsf-input-id')}.value = "Enter something here";

You can view the HTML source when this is generated and see what the id is set to, so you can use that in your JavaScript. As it's in a form it is probably prepending the form id to it.

I know this is not the JSF way but if you want to avoid the ID pain you can set a special CSS class for the selector. Just make sure to use a good name so that when someone reads the class name it is clear that it was used for this purpose.
<h:inputText id="emailAddresses" class="emailAddressesForSelector"...
In your JavaScript:
jQuery('.emailAddressesForSelector');
Of course you would still have to manually manage class name uniqueness.
I do think this is maintainable as long as you do not use this in reusable components. In that case you could generate the class names using a convention.

<h:form id="myform">
<h:inputText id="name" value="#{beanClass.name}"
a:placeholder="Enter Client Title"> </h:inputText>
</h:form>
This is a small example of jsf. Now I will write javascript code to get the value of the above jsf component:
var x = document.getElementById('myform:name').value; //here x will be of string type
var y= parseInt(x,10); //here we converted x into Integer type and can do the
//arithmetic operations as well

Related

create links dynamically

I have a user-defined text, such as
#SessionScoped
public class MyBean {
private String text = "Life’s but a walking shadow, a poor player
that struts and frets his hour upon the stage and
then is heard no more.";
public String getText() {
return text;
}
}
Of course the text is not static, but will be loaded from somewhere else. I want the text to be displayed one the page, as in
<h:form id="myForm">
<h:outputText value="#{myBean.text}" />
</h:form>
Now have a logic in the bean which marks certain words, e.g. every noun, in the text. These words should be rendered as links, as if they were commandLinks.
That is, the form should be submitted and I should be able to find out which link was clicked.
Something similar was already asked here, here and here, but I am not sure if the solutions given there suit my case.
My best guess right now is to split the text at the marked words into a list of snippets in the bean, e.g.
List<TextSnippet> textSnippets;
class TextSnippet {
private String precedingText;
private String markedWord;
...
}
such that each text snippet ends with a marked word. Then I would be able to iterate over the list in the xhtml, e.g.
<h:form id="myForm">
<ui:repeat var="snippet" value="#{myBean.textSnippets}">
<h:outputText value="#{snippet.precedingText}" />
<h:commandLink action="#{myBean.clickedOn(snippet.markedWord)}">
<h:outputText value="#{snippet.markedWord}">
</h:commandLink>
</ui:repeat>
</h:form>
However, I feel that this tightly couples the bean (logic of splitting) to the view. Any better ideas?
What I would personally do is try to keep the jsf tree small and implement something like the lines below that I think is more performant (disclamer: no full code coming )
Prepare the text serverside in a bean as This is a <div class="linkedWord">specific</div> word that needs a link and so is <div="linkedWord">this</div>
Output this in plain html via an <h:outputText value="#{myBean.text}"> (for escaping!)
Add a jquery dynamic eventhandler on the class="linkedWord" (so it works for each link) and call a javascript function
In that javascript function read the content of the div (or maybe add the text as a data- attribute aas well (like <div class="linkedWord" data-word="specific">specific</div>
and call a <h:commandScript> (JSF 2.3 and up) or a o:commandScript for previous JSF versions (or the `p:remoteCommand) and pass the content of the div (or the value of the attribute) as a parameter to a serverside method.
Keep in mind that there is no explicit reason to do everything in a 'JSF' way. Using client-side features and some small integration with JSF is very valid usage. People not doing this often 'blame' JSF but they themselves are effectively the cause of the less optimal behaviour)
See also:
Event binding on dynamically created elements?
http://omnifaces.org/docs/javadoc/2.6/org/omnifaces/component/script/CommandScript.html
https://javaserverfaces.github.io/docs/2.3/vdldocs/facelets/h/commandScript.html
You seem to go the right way, but I think I can suggest you some improvements. Don't know your exact requirements, but your current structure limits the marked word (which I guess acts as a mere link) to be at the end of the paragraph. What would happen if you have text after it? What about having two marked words? This class might suit better:
class TextSnippet {
private String text;
private String linkUrl;
...
}
You'll need to build the List<TextSnippet> the way you do, but evaluate the links before, so ui:repeat can access them.
Then, iterate over it. Instead of performing a POST to evaluate where to go, you've got it already, so you can use a h:link if you want to point to somewhere in your application or h:outputLink if it's outside it:
<ui:repeat var="snippet" value="#{myBean.textSnippets}">
<h:outputText value="#{snippet.text}" rendered="#{empty snippet.linkUrl}" />
<h:link outcome="#{snippet.linkUrl}" rendered="#{not empty snippet.linkUrl}">
<h:outputText value="#{snippet.text}">
</h:link>
</ui:repeat>

Button do not work jsf [duplicate]

I am trying to implement jQuery with PrimeFaces and JSF components, but it's not working properly. When I tried to do the same with HTML tags it;s working properly.
Here is the code with HTML tags which works properly with jQuery:
<input type="checkbox" id="check2"></input>
<h:outputText value="Check the box, if your permanent address is as same as current address."></h:outputText>
<h:message for="checkbox" style="color:red" />
with
$("#check2").change(function() {
if ($("#check2").is(":checked")) {
$("#p2").hide();
} else {
$("#p2").show();
}
});
Here is the code with PrimeFaces/JSF which doesn't work properly with jQuery:
<p:selectManyCheckbox >
<f:selectItem itemLabel="1" value="one" id="rad" ></f:selectItem>
</p:selectManyCheckbox>
with
$("#rad").change(function() {
if ($("#rad:checked").val() == "one") {
$("#p2").hide();
} else {
$("#p2").show();
}
});
You should realize that jQuery works with the HTML DOM tree in the client side. jQuery doesn't work directly on JSF components as you've written in the JSF source code, but jQuery works directly with the HTML DOM tree which is generated by those JSF components. You need to open the page in webbrowser and rightclick and then View Source. You'll see that JSF prepends the ID of the generated HTML input elements with the IDs of all parent NamingContainer components (such as <h:form>, <h:dataTable>, etc) with : as default separator character. So for example
<h:form id="foo">
<p:selectManyCheckbox id="bar" />
...
will end up in generated HTML as
<form id="foo" name="foo">
<input type="checkbox" id="foo:bar" name="foo:bar" />
...
You need to select elements by exactly that ID instead. The : is however a special character in CSS identifiers representing a pseudo selector. To select an element with a : in the ID using CSS selectors in jQuery, you need to either escape it by backslash or to use the [id=...] attribute selector or just use the old getElementById():
var $element1 = $("#foo\\:bar");
// or
var $element2 = $("[id='foo:bar']");
// or
var $element3 = $(document.getElementById("foo:bar"));
If you see an autogenerated j_idXXX part in the ID where XXX represents an incremental number, then you must give the particular component a fixed ID, because the incremental number is dynamic and is subject to changes depending on component's physical position in the tree.
As an alternative, you can also just use a class name:
<x:someInputComponent styleClass="someClassName" />
which ends up in HTML as
<input type="..." class="someClassName" />
so that you can get it as
var $elements = $(".someClassName");
This allows for better abstraction and reusability. Surely those kind of elements are not unique. Only the main layout elements like header, menu, content and footer are really unique, but they are in turn usually not in a NamingContainer already.
As again another alternative, you could just pass the HTML DOM element itself into the function:
<x:someComponent onclick="someFunction(this)" />
function someFunction(element) {
var $element = $(element);
// ...
}
See also:
How can I know the id of a JSF component so I can use in Javascript
How to use JSF generated HTML element ID with colon ":" in CSS selectors?
By default, JSF generates unusable IDs, which are incompatible with the CSS part of web standards
Integrate JavaScript in JSF composite component, the clean way
You also can use the jQuery "Attribute Contains Selector" (here is the url http://api.jquery.com/attribute-contains-selector/)
For example If you have a
<p:spinner id="quantity" value="#{toBuyBean.quantityToAdd}" min="0"/>
and you want to do something on its object you can select it with
jQuery('input[id*="quantity"]')
and if you want to print its value you can do this
alert(jQuery('input[id*="quantity"]').val());
In order to know the real html tag of the element you can always look at the real html element (in this case spinner was translated into input) using firebug or ie developer tools or view source...
Daniel.
If you're using RichFaces you can check rich:jQuery comonent. It allows you to specify server side id for jQuery component. For example, you have component with specified server id, then you can apply any jQuery related stuff to in next way:
<rich:jQuery selector="#<server-side-component-id>" query="find('.some-child').removeProp('style')"/>
For more info, please check doumentation.
Hope it helps.
look this will help you when i select experience=Yes my dialoguebox which id is dlg3 is popup.and if value is No it will not open

commandlink in JSF not generating the intended HTML tag

I'm trying to call a managed bean from h:commandLink in JSF. But I don't see href attribute in the rendered HTML a tag.
Am I missing something?
There is a ManagedBean called AccountSetupController with a signUp method in it.
This is the tag I used in JSF:
<h:form prependId="false">
<h:commandLink action="#{accountSetupController.signUp()}"
value="#{msg['homepage.createaccount']}" styleClass="button large">
</h:commandLink>
</h:form>
This is the rendered tag. See there is nothing in href attribute.
<a href="#" onclick="mojarra.jsfcljs(document.getElementById('j_idt15'),
{'j_idt33':'j_idt33'},'');return false"
class="button large">CREATE MY ACCOUNT</a>
This is the form tag that is generated
<form id="j_idt15" name="j_idt15"
method="post" action="/myproject/faces/homepage/homepage.xhtml"
enctype="application/x-www-form-urlencoded"> .... </form>
As you can see, the form action is pointing to some place I don't need.
Am I missing something?
Command links in JSF are rendered that way. The form will be submitted by JSF via JavaScript's onclick method using JSF JS library, while the href will always stay #.
Moreover, you won't find the bound action / action listener method names in browser tools due to understandable reasons. Rather, JSF will find the id of a clicked link on the server and will trigger all of the component's action(listeners).
All in all, reading <h:commandLink> documentation unsurprisingly helps a lot (all emphasis mine):
General behavior: Both the encode and decode behavior require the ability to get the id/name for a hidden field, which may be rendered in markup or which may be programmatically added via client DOM manipulation, whose value is set by the JavaScript form submit (further referred to as hiddenFieldName.
Decode behavior: Obtain the "clientId" property of the component. Obtain the Map from the "requestParameterMap" property of the ExternalContext. Derive hiddenFieldName as above. Get the entry in the Map under the key that is the hiddenFieldName. If the there is no entry, or the entry is the empty String, or the entry is not equal to the value of the "clientId" property, return immediately. If there is an entry, and its value is equal to the value of the "clientId" property, create a new javax.faces.event.ActionEvent instance around the component and call queueActionEvent() on the component, passing the event.
Encode behavior: Render "#" as the value of the "href" attribute. Render the current value of the component as the link text if it is specified. Render JavaScript that is functionally equivalent to the following as the value of the "onclick" attribute: document.forms['CLIENT_ID']['hiddenFieldName'].value='CLIENT_ID'; ocument.forms['CLIENT_ID']['PARAM1_NAME'].value='PARAM1_VALUE'; document.forms['CLIENT_ID']['PARAM2_NAME'].value='PARAM2_VALUE'; return false; document.forms['CLIENT_ID'].submit()" where hiddenFieldName is as described above, CLIENT_ID is the clientId of the UICommand component, PARAM*_NAME and PARAM*_VALUE are the names and values, respectively, of any nested UIParameter children.

Primefaces RequestContext scrollTo does not work

Primefaces v3.5
Trying to use RequestContext.getContext().scrollTo("") to scroll to my form programmatically at the end of an ajax request.
XHTML snippets:
<h:form id="genericMessagesForm">
<p:messages id="genericMessages" />
</h:form>
<p:commandButton id="testButton"
value="Test" process="#{cc.attrs.itemName}Final, #this"
actionListener="#{myBean.methodCalledByAjax()}" />
Bean:
public void methodCalledByAjax() {
List<String> updateTargets = new ArrayList<String>();
updateTargets.add("currentRecordForm");
updateTargets.add("genericMessagesForm");
RequestContext.getCurrentInstance().update(updateTargets);
RequestContext.getCurrentInstance().scrollTo("genericMessagesForm");
}
Update does work.
ScrollTo does NOT work (same ID!).
No server errors thrown.
No javascript console errors thrown.
Browsers tried: Firefox (latest), Chrome (latest), IE8.
Did you look in the documentation? Here's a cite from the RequestContext#scrollTo() javadoc:
scrollTo
public abstract void scrollTo(String clientId)
Scroll to a component after ajax request is completed.
Parameters:
clientId - Client side identifier of the component.
Look, it says client ID, not component ID. It makes also sense, the scrolling job is ultimately done by JavaScript via document.getElementById() and friends. That works only with a client ID.
For starters who haven't memorized the whole NamingContainer thing, an easy way to figure the right client ID is by looking at the JSF-generated HTML output via rightclick, View Source in webbrowser.
For a
<h:form id="genericMessagesForm">
<p:messages id="genericMessages" />
</h:form>
that's thus something like
<form id="genericMessagesForm" ...>
<div id="genericMessagesForm:genericMessages" ...>
...
</div>
</form>
So, fix the call accordingly:
requestContext.scrollTo("genericMessagesForm:genericMessages");
By the way, if the form contains solely the <p:messages>, then you can alternatively also just get rid of the whole form altogether. The <p:messages> is not an EditableValueHolder nor ActionSource component and does therefore not require to be placed in an UIForm component. This way you can keep using your initial attempt.
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"

Is there a way to use EL to get the current value of an h:inputText field?

I'm new to JSF and EL, and was wondering if there is a way to use EL to get the current value of an h:inputText field. Am I doing it wrong, or is it possible at all?
Thanks,
-Ben
(Based on your comment) If you want to validate it server-side then you should look at an Ajax library like Richfaces.
You can then easily add an ajax call to your input field
<h:inputText id="myInput" value="#{myBean.myValue}">
<a4j:support event="onchange" ajaxSingle="true"/>
</h:inputText>
When you change the text the Ajax call will update your model on the Server-side. If you have a validator then you can add it to the inputText tag or use the action attribute on the support tag to call another method.
I don't really understand what you are looking for...
With this code:
<h:form id="myForm">
<h:inputText id="myInput" value="#{myBean.myValue}"/>
The value of the input field, at the creation of the HTML page, will be equal to the value of the myValue property of the bean myBean.
If the value is changed by the user, JSF will automatically update the value of myBean.myValue when the form will be submitted.
If you need to get the value of the input on the client side, i.e. using Javascript, you need to do the following code:
<script type="text/javascript">
function getInputTextValue() {
var valueOfInput = document.getElementById("myForm:myInput").value;
}
</script>
Note that you must prefix the ID by the ID of the form that contains the input ("**myForm:**myInput").

Resources