JSF Ajax called only 1st time - jsf-2

In JSF2 I have an XHTML like this:
<h:form id="myForm">
...
<c:forEach items="#{myController.header}" var="hd" varStatus="count">
#{hd}
<h:selectOneMenu value="#{myController.type[count.index]}" id="formtype" >
<f:selectItem itemValue="Nop" itemLabel="Nop" />
<f:selectItem itemValue="Yep" itemLabel="Yep" />
<f:ajax render="#form" />
</h:selectOneMenu>
#{myController.type[count.index]}
<h:selectBooleanCheckbox value="#myController.valid[count.index]}" id="valid">
<f:ajax render="#form"/>
</h:selectBooleanCheckbox>
#{myController.valid[count.index]}
</c:forEach>
...
</h:form>
And my managed bean has:
private String[] type;
private boolean[] valid;
which I initialise (type = new String[...]; and assign a value to each position) when the named bean is 1st loaded.
If I modify the combo or the check box, it works, the value is changed in the managed bean and the new value gets printed (rendered) in the JSF page. But only the 1st time. Next changes do not modify anything at all. It is strange because I have similar code in other apps and works fine, so I am doing something incorrectly but cannot find it. My template has a h:header and I cannot see any logs in the JS console or in TomEE (I only see .INFO - The start() method was called on component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/myApp]] after start() had already been called. The second call will be ignored but I think it is unrelated). I have tried to add execute="#this"/execute="#form" and others unsuccessfully, and check all points of this post but nothing seems to apply to me.
What is the mistake I am not seeing?
EDIT
#Named(value = "myController")
#ViewScoped
public class MyController implements Serializable {
...
I also have a <h:messages globalOnly="true" showDetail="true" showSummary="true" /> in my template.

I think I got it, finally!
Thanks to two things:
Point 3 in BalusC answer. I added an id to my message in the template <h:messages id="msg" and then use <f:ajax render="#form msg"..... This made an error j_idt1: Validation Error: Value is required to appear.
Then I could find the solution in this post: to change the required parameter from true to <f:viewParam required="#{!facesContext.postback}". This was not required in my other apps because required was "false", since it could be called with parameter or without it. When it was called with a parameter, it worked because by serendipity the page could be called without it.

Ran into the exact same problem, my <f:ajax> tag would work the first time and then nothing... no error or anything on the page. After a few hours and countless googling nothing was turning up. (Most of the questions on StackOverflow were actually having the opposite problem, the Ajax wouldn't fire the first time but then it would work fine). I finally stumbled on this question which described exactly what I was seeing.
I was previously trying to re-render only a section of the page, but I noticed that once I changed the render attribute to "#all", I got the same error message describe above:
j_idt1: Validation Error: Value is required
I scrolled up and noticed I had a <f:viewParam> with required set to "true". I made the change described by user1156544 and that did the trick.

Related

JSF Validation error not printed in open dialog

I have to validate that a field in a form is not empty.
The problem is that the form is in a JQueryUI dialog (since I don't know how to create "windows" in JSF), so when I click the commandButton the page is refreshed and the JQuery dialog is lost. After refreshing, I can see the error message was printed in the page code by looking at the source code. If I use ajax in the commandButton then the page is not refreshed but I don't get the message printed, I got it as a sort of "Javascript alert" in the browser.
How can I get the error message without refreshing the page?
<h:inputText value="#{myController.name}" id="myname" required="true" requiredMessage="Name required">
<f:ajax />
</h:inputText>
<h:message errorClass="..." for="myname" />
Note: This looked similar to my problem but I don't think the solution is what I'm looking for.
Note: I am not using additional libraries like Primefaces, etc
With the hint of the comment, I was able to solve it this way:
In the commandButton, use ajax with both render and execute (render only doesn't work):
<h:commandButton id="...." action="#{myController.doSomething()}" type="submit" value="Do something">
<f:ajax execute="#form" render="#form" />
</h:commandButton>
Create a "pageUpdate()" method in myController that is called at the end of myController.doSomething(). This way, after the actions, the page is refreshed and the dialog is gone. There are of course other ways to close the dialog, but it is convenient for me to update the page when there is no error in the dialog action, so my objects in memory are updated too.
I think JQuery dialog messes with my styles after the ajax call returns with error, so check that out if you do it.

<ui:repeat> inside <ui:repeat> displaying data more number of times

0 and i need to render some buttons based on condition, i'm getting the condition true but each time i visit the page the button its displaying with additionl buttons,here's my code
<ui:repeat var="r" value="#{sessionScope['restrictpageload']}" varStatus="status">
<ui:repeat var="permission" value="#{restrictPageLoad.isUserHasFeaturePermission(4,'abc')}" varStatus="status2">
<ui:fragment rendered="#{permission.featureCreate eq 'y'}" >
<h:commandButton value="Button1" action="#{bean.method()}"/>
</ui:fragment>
</ui:repeat>
</ui:repeat>
here my first <ui:repeat> gets the values from session and i'll pass as parameter to second and this will return me arraylist and i'm going to render the button based on condition.
I'm getting the values inside but each time i visit page two more button addsup.Please help.
too long for a comment...
3 points:
outer loop declares r and status which are not used in inner loop, so "here my first <ui:repeat> gets the values from session and i'll pass as parameter to second" is false
value="#{sessionScope['restrictpageload']}" is equivalent to value="#{restrictpageload}"
value="#{sessionScope['restrictpageload']}" maybe there's a typo. you mean value="#{sessionScope['restrictPageload']}" (uppercase P)
maybe you want to do something like this:
<ui:repeat var="restriction" value="#{bean.pageRestrictions}">
<ui:repeat var="permission" value="#{bean.userPermissions}">
<ui:fragment rendered="#{restriction == permission}">
<h:commandButton value="Button1" action="#{bean.method}"/>
</ui:fragment>
</ui:repeat>
</ui:repeat>
or better
<ui:repeat var="restriction" value="#{bean.pageRestrictions}">
<ui:fragment rendered="#{bean.userHasFeaturePermission(restriction)}">
<h:commandButton value="Button1" action="#{bean.method}"/>
</ui:fragment>
</ui:repeat>
however if your buttons are duplicating, you are adding something to your loops, maybe in isUserHasFeaturePermission?
UPDATE (comment reply)
read carefully the accepted answer of your linked question:
Your question is meaningless. There is no "passing parameters by " and there is no "passing parameters using ". Your words might make sense in some specific context - but the context is missing.
not related but worth mention, NEVER use c:forEach in JSF pages, unless you know exactly how JSF lifecycle works.
passing parameters in expressions depends on EL (ExpressionLanguage) library version.
you can pass parameters only if you have EL 2.2+. this library is shipped (normally) with the servlet container.
read this answer and linked for a complete explanation.
what's your servlet container? tomcat 6.0, glassfish 3.1?
however, does it throws an Exception?

h:selectOneMenu with Please select displays previous selection on validation error

I am using Spring Webflow 2.4.0.M1 with Mojara JSF 2.1.21.
I have a very simple h:selectOneMenu like so:
<h:selectOneMenu id="title" value="#{person.title}" required="true" requiredMessage="Required title">
<f:selectItem noSelectionOption="true" itemLabel="Please Select" itemValue="" />
<f:selectItem itemLabel="Mr" itemValue="MR" />
<f:selectItem itemLabel="Mrs" itemValue="MRS" />
</h:selectOneMenu>
<p:message for="title"/>
After submitting the form with the value left on Please Select, I get the required message displayed. If I then choose option 'Mr', and then submit again, but with other fields on the page having errors, then the page is reloaded, and the required message for title is gone and Mr is selected, as expected. If I then change it back to Please Select and submit again, I get the required message display again, but the selected option has gone back to being 'Mr' instead of 'Please Select'. The #{person.title} EL is binding to a String, which is defaulted to an empty string. So far, this only seems to be an issue on selectOneMenu, as doing the same kind of thing on a h:inputText works correctly.
Any ideas? Have also tried with webflow 2.3.2.RELEASE and same issue occurs.
Looks like it is the same issue as this: JAVASERVERFACES-932 which is about 4 years old, and has a resolution of fixed. It's definitely not fixed. I will try extending the MenuRenderer and overriding the renderOption method with the suggestion mentioned at the end of the Jira issue.
I can confirm that extending MenuRenderer and overriding the renderOption method with the suggestion mentioned at the end of the Jira issue fixes the issue.
Don't forget to add your patched renderer to your faces-config.xml
<render-kit>
<renderer>
<component-family>javax.faces.SelectOne</component-family>
<renderer-type>javax.faces.Menu</renderer-type>
<renderer-class>your.package.PatchedMenuRenderer</renderer-class>
</renderer>
</render-kit>

p:commandlink inside ui:repeat

In our application we are displaying the menus dynamically. We have the menu object(menuitems in below code) populated with all the menu items (read from an xml). The home page then generates the menus by usinng ui:repeat. Insdie ui:repeat there are p:commandlink.
Below is the code
<h:form id="mainMenu">
<h:panelGroup id="MMPanel" layout="block" styleClass="left_menu">
<ui:repeat var="node" value="#{menuitems.level1menus}">
<p:commandLink immediate="true" styleClass="menu"
action="#{menuitems.onLevel1MenuChange(node.id)}"
update=":pageTitle :menuLevel2 :menuLevel3" title="#{node.name}"
rendered="#{menuitems.selectedLevel1.id!=node.id}" onclick="menuSelect(this)">
<span class="icon icon_#{node.name}"></span>
<span class="text">#{node.name}</span>
</p:commandLink>
<p:commandLink immediate="true" styleClass="menu activelink"
action="#{menuitems.onLevel1MenuChange(node.id)}"
update=":pageTitle :menuLevel2 :menuLevel3" title="#{node.name}"
rendered="#{menuitems.selectedLevel1.id==node.id}" onclick="menuSelect(this)">
<span class="icon icon_#{node.name}"></span>
<span class="text">#{node.name}</span>
</p:commandLink>
</ui:repeat>
</h:panelGroup>
</h:form>
The menuitems bean is at Session level.
There are two diffeent p:commandlink inside ui:repeat. The only difference between the 2 is in the styleclass and rendered attribute. This is done to identify the default menu item when the user logs for the first time and give it an extra css of "activeLink".
The java script called on onclick is given below (in case it is required)
function menuSelect(selectOne){
$(".left_menu>a").removeClass("activelink");
$(selectOne).addClass("activelink");
removeAllChannels();
}
function removeAllChannels(){
$.atmosphere.unsubscribe();
}
The removeAllChannels is to remove primepush autorefresh channels we have.
The issue i am facing is this.
All the links are getting rendered correctly and in Firebug i see all of them have the same html.
But the one which is generated with the extra css "activeLink" (through rendered condition -- menuitems.selectedLevel1.id==node.id) is not working. Nothing happens when i click this default link. All other links work fine.
So when i click on a different link, it takes me to the required page. But when i click back on the menu which was default, nothing happens
I added a Custom phase listener and saw that all the lifecyle stages are called when this link is clicked but the action method is not.
I went through the links this and this but could not figure out the issue.
Please help.
Do tell me if something is not clear
As part of safeguard against tampered/hacked requests, the JSF component's rendered attribute is re-evaluated during processing the form submit. In case of a command link/button, if it evaluates false, then its action won't be queued/invoked. This matches the symptoms you're seeing.
This can in turn happen if the managed bean #{menuitems} is request scoped and/or when the properties behind #{menuitems.level1menus} or #{menuitems.selectedLevel1} are incompatibly changed during the postback request.
Putting the bean in the view scope and ensuring that the getters do not do any business job should fix this problem.
See also:
How to choose the right bean scope?
commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 5 applies to you

Unique ID for JSF composite component inside dataTable

I am using PrimeFaces 3.2 with JSF 2 in a glassfish 3.1.2.
I have a <p:dataTable> which displays search results containing information on different issues (the issues are assigned to users).
If somebody clicks on the icon of the assigned user a <p:dialog> pops up.
The user icon and the according dialog are implemented using a composite.
Inside the composite I am using some jQuery functions which need a unique ID for each dialog component - I am not able to find a way to solve this problem.
My investigations so far:
I need to set the widgetVar attribute, which works fine as long as I have only one user in the list but it seems that inside a dataTable the widgetVar is not unique for many composites.
Since the user can be displayed more than one time inside the search result, I am not able to setup an widgetVar like this:
<ui:param name="myWidgetVar" value="widget_#{user.id}" />
and use it this way
<p:dialog widgetVar="#{myWidgetVar}">
also using #{cc.id} does not resolve the problem 'cause it only returns the id of the widget without the naming-container part which is always the same.
I need the complete id as displayed in html (e.g.: form:jdt123:dialog:456) - how can I get this?
Does anyone know what to do?
Thanks Pete
My solution is using #{cc.clientId} which I did not know yet.
This gives me the complete html element id constisting of the series of identifiers glued with the UINamingContainer#getSeparatorChar (e.g.: form:jdt123:dialog:jdt456)
Thanks for the answer. You solved my unrelated problem, but I think I stumbled on another solution for your problem.
From the PrimeFaces user guide (http://primefaces.org/documentation.html):
8.2 EL Functions
PrimeFaces provides built-in EL extensions that are helpers to common use cases.
Common Functions
Component
<h:form id="form1">
<h:inputText id="name" />
</h:form>
//#{p:component(‘name’)} returns ‘form1:name’
WidgetVar
<p:dialog id="dlg">
//contents
</p:dialog>
<p:commandButton type="button" value="Show" onclick="#{p:widgetVar(‘dlg’)}.show()" />
It looks like you would be most interested in the WidgetVar implementation.

Resources