I have two image buttons:
<div class="sidebarOptions">
<input type="image" src="images/homeButton.jpg" onclick="#{home.setRendered(1)}"/>
</div>
<div class="sidebarOptions">
<input type="image" src="images/memberButton.jpg" onclick="#{home.setRendered(2)}"/>
</div>
However, the both methods are immediately invoked when the page loads with values 1 and 2. Also when I click it, the both methods are invoked.
How can I achieve the desired functionality of only calling the bean method when the image button is actually clicked?
This approach will not work. You seem to be confusing/mixing the basic web development concepts of the "server side" and "client side" and to be misunderstanding the role of JSF and EL.
JSF is a server side language which runs on the webserver upon a HTTP request and produces HTML/CSS/JS code which get returned with the HTTP response. All EL expressions in form of ${} and #{} will be executed in the server side during generating the HTML output. JavaScript is a client side language which runs on the webbrowser and works on the HTML DOM tree. The HTML onclick attribute should specify a JavaScript function which will be executed in the client side on the particular HTML DOM event.
In order to invoke a JSF managed bean method, you need the action or *listener attribute. JSF provides components to generate the desired HTML and specify the desired ajax actions which would change the server side state. An <input type="image"> can be generated using a <h:commandButton image>. A bean method can be invoked by the action attribute of that component. That component can be ajaxified by embedding the <f:ajax> tag.
So, the following should do it for you:
<h:form>
<div class="sidebarOptions">
<h:commandButton image="images/homeButton.jpg" action="#{home.setRendered(1)}">
<f:ajax execute="#this" render=":sidebar" />
</h:commandButton>
</div>
<div class="sidebarOptions">
<h:commandButton image="images/memberButton.jpg" action="#{home.setRendered(2)}">
<f:ajax execute="#this" render=":sidebar" />
</h:commandButton>
</div>
</h:form>
<!-- The below is just a guess of what you're really trying to achieve. -->
<h:panelGroup id="sidebar" layout="block">
<h:panelGroup rendered="#{home.rendered eq 1}">
Home
</h:panelGroup>
<h:panelGroup rendered="#{home.rendered eq 2}">
Member
</h:panelGroup>
</h:panelGroup>
See also:
Differences between action and actionListener
How to invoke a managed bean action method in on* attribute of a JSF component
How to invoke a JSF managed bean on a HTML DOM event using native JavaScript?
Related
I have a list of autocompletes that is rendered using a p:dataList. Something like shown below:
<h:panelGroup layout="block" id="outerPanel">
<p:dataList rendered="#{bean.myModel.listOfItems.size()>0}"
var="additionalMP"
value="#{bean.myModel.listOfItems}"
rowIndexVar="index" emptyMessage="">
<div class="wrapper ui-g">
<div>
<p:autoComplete
cache="true"
value="#{bean.myModel.listOfItems[index]}"
completeMethod ="#{handler.getAutoCompleteData}"
rendered ="true"
required="false"
scrollHeight="200"
styleClass="custom"
forceSelection="true">
<p:ajax event="query" global="false"/>
<f:attribute name="filter" value="filterName" />
<f:attribute name="mode" value="edit" />
</p:autoComplete>
</div>
<div>
<p:commandLink value="+ Add" actionListener="#{bean.addAutoComplete()}"
update=":formName:outerPanel"></p:commandLink>
</div>
</div>
</p:dataList>
</h:panelGroup>
So, the Add button inserts a new item in the list and I update the container panel so that the newly added item can be rendered on the UI.
As expected the panel is updated and I see another autocomplete on the UI. But the problem is, all the auto completes now don't work. i.e. they stop firing the query event and don't give any suggestions.
Edited: The partial response that updates the section of form with autocomplete fields, contains some script tags, which probably execute on page ready/load event. So I know that basically the newly added prime faces widgets are not being initialized.
Any idea how I can initialize the newly added autocompletes in the DOM?
The reason for all this trouble was an error in javascript that was caused by trying to scrollTo a particular element on the page from the bean. This crappy line of code in the bean was the source of all the trouble. There was no element on the page with the id messages. A glaring example of why UI should not be coupled in such a way.
RequestContext.getCurrentInstance().scrollTo("formId:messages");
According to the documentation, it should be possible to explicitly declare that a form input
element component receives focus via the 'for' attribute.
In this case, the second visible and enabled input element rather than the first by default -
so can someone please help me by explaining why the following doesn't work?
<h:form id="form4">
<p:focus id="pick" for="input2" />
<h:inputText id="input1" value="#{messageManagedBean.message1}"/>
<h:inputText id="input2" value="#{messageManagedBean.message2}"/>
<p:commandButton value="Execute JSF Lifecycle - Invoke Action One" action="#{messageManagedBean.doSomeAction41}" ></p:commandButton>
<p:commandButton value="Execute JSF Lifecycle - Invoke Action Two"
action="#{messageManagedBean.doSomeAction42}" ></p:commandButton>
<p:messages for="input1" id="messages1" autoUpdate="true"/>
<p:messages for="input2" id="messages2" autoUpdate="true"/>
</h:form>
Many thanks!
[PrimeFaces: 3.5.25
JavaServer Faces: 1.2
Java Servlet: 2.5
Server: Apache Tomcat 8.0.15]
If you check the source of the p:focus renderer, you will see (in case you set for) the component is resolved and a bit of JavaScript is written:
writer.write("$(function(){");
writer.write("PrimeFaces.focus('" + clientId +"');");
writer.write("});");
Since it's not working for your software stack, you could omit p:focus and simply write the JavaScript yourself:
<h:form id="form4">
<script>
$(function(){ PrimeFaces.focus('form4:input2'); });
</script>
<h:inputText id="input1" value="#{messageManagedBean.message1}"/>
<h:inputText id="input2" value="#{messageManagedBean.message2}"/>
...
</h:form>
Yes, this is a hack. If you can, upgrade your software stack. For me your XHTML is working.
I want to get current view HTML source and pass it to JSF managed bean as a parameter. Is there anyway in JSF I can do this?
You can't do it in JSF as it doesn't run in the webbrowser at all.
Your best bet is using JavaScript. The below example sets a hidden input value with the HTML source code when the submit button is clicked:
<h:form id="form">
<h:inputHidden id="source" value="#{bean.source}" />
<h:commandButton value="submit" action="#{bean.submit}"
onclick="document.getElementById('form:source').value=document.getElementsByTagName('html')[0].outerHTML"
/>
</h:form>
In the action method, it's in the particular example then just available by the source property.
I am createing page using JSF 2.0:
<h:selectBooleanCheckbox id="checkbox1" title="Published"
onclick="#{StageGate.setMyCheckboxValue()}" />
I was expecting setMyCheckboxValue() to be called whenever checkbox is clicked. However, setMyCheckboxValue() is called once when page is loaded.
If I write
<h:selectBooleanCheckbox id="checkbox1" title="Published"
onclick="#{StageGate.setMyCheckboxValue()}; alert(document.getElementById('checkbox1').checked);" />
I get alert for each click.
My Question is: When I am getting alert, why setMyCheckboxValue() is not getting called on each onclick event?
Note: I also tried AJAX, but the checkbox remains constant.
The onclick attribute is for client side (javascript) methods and will not change anything on the server side.
If you want to change a server side value you need the value attribute:
<h:selectBooleanCheckbox value="#{StageGate.myCheckboxValue}" .../>
Note that I changed your setMyCheckboxValue() to myCheckboxValue because the setter method is automatically detected by jsf (if you correctly define your variable foo with the getter getFoo() and the setter setFoo(...))
onclick is used for client side javascript calls.
I think you want to call a function on server side, when a checkbox is clicked.
Here is the code:
<h:selectBooleanCheckbox id="checkbox1" title="Published"
value="#{StageGate.myCheckBox}" >
<f:ajax event="change" execute="#this"
action="#{StageGate.setMyCheckboxValue()}" />
</h:selectBooleanCheckbox>
I hope this will work for you.
I have a JSF2 application and a page with the following code:
<h:inputText id="someInput" required="true" />
<p:outputPanel id="itemsPanel">
<ui:repeat var="i" value="#{myBean.itemIndices}" id="items">
<h:inputText
id="itemInput"
value="#{myBean.dataItems[i]}"
/>
<h:panelGroup
layout="block"
styleClass="clear"
rendered="#{((i+1) % 10 == 0)}"
/>
</ui:repeat>
</p:outputPanel>
<br/>
<p:commandButton
classStyle="btn"
value="Add Row"
actionListener="#{myBean.increaseItemsCount}"
update="itemsPanel"
immediate="false"
ajax="true"
/>
The ui:repeat is dynamically rendering a number if text boxes depending on the itemIndices and dataItems properties. The "Add Row" button calls a method that will dynamically increase the number of itemIndices and dataItems, therefore additional text inputs appear.
The current code will not work if there is no value in the text box someInput, because the AJAX request also validates the form and validation fails. Pressing the button in this case has no visual effect, not even feedback for the user that validation did not pass (because I update itemsPanel only).
If I change the button to have immediate="true", then the validation issue is no more. Unfortunately, I want to be able to restore the values of the dynamic input fields that the user might have changed prior adding the new row. The immediate="true" attribute causes the form not to be submitted to the server, therefore the user-entered data will not be persisted.
A possible solution to this could be to add process="all dynamic input ids csv" attribute to the command button and set the immediate attribute back to true. This will cause the server to validate only the inputs specified in the process attribute and they will be persisted. The problem here is that these input ids are dynamically generated by JSF and I cannot come up with a proper way to get them as a CSV. I would also not prefer a solution for dynamically generating ids in myBean relying on assumptions of how JSF would output them.
All suggestions will be greatly appreciated.
You could use process="itemsPanel".
<p:commandButton
classStyle="btn"
value="Add Row"
actionListener="#{myBean.increaseItemsCount}"
process="itemsPanel"
update="itemsPanel"
ajax="true"
/>
You should only move the command button into <h:outputPanel id="itemsPanel">.