JSF 2 problem. I have a hidden edit area on my form. When the user clicks the Edit button, I set a bean property to true to display the area (this is a bit of a simplification) and set another bean property to the value being edited. This variable is referred to like:
<h:inputText value="#{bean.stringValue}" />
When the user cancels out of editing, I hide the edit area.
Let's say the user then wants to edit another item, but this one's value is the empty string (""). Using the same code, stringValue is set to the emptyString and the area displays.
However, the value from the previous edit is displayed, not an empty text box.
Without resorting to JavaScript, is there a way to make this work?
Edit: Following is as close as I can come to a SSCCE. As you see, I am activating in-place editing inside a table. I'm also using ICEfaces, but nothing special in this case.
<table>
<tbody>
<ui:repeat var="cfi"
value="#{evDetailBean.completeEvent.listCompleteCashFlowItems}">
<ice:panelGroup rendered="#{!cfi.editThisOne}">
<tr>
<td>#{cfi.cfiName}</td>
<td>#{cfi.absOfAmount}</td>
<td>#{cfi.frequencyDescr}</td>
<td>#{cfi.cfiToFrom}</td>
<td>#{cfi.assetPoolName}</td>
<td style="text-align: center"><h:commandLink
actionListener="#{cfi.editCfiListener}" value="Edit" /> <h:commandLink
value="Delete" actionListener="#{cfi.deleteCfiListener}" />
</td>
</tr>
</ice:panelGroup>
<ice:panelGroup rendered="#{cfi.editThisOne}">
<tr>
<td><ice:inputText value="#{evDetailBean.newCFIName}"
style="width:118px;" partialSubmit="true" immediate="true" validator="#{evDetailBean.valNewCFIName}" /></td>
<td>xxx</td>
<td>xxx</td>
<td>xxx</td>
<td>xxx</td>
<td style="text-align: center;"><ice:commandButton
value="Save" immediate="true"
actionListener="#{evDetailBean.saveEditCfiListener}"
styleClass="plumvo-button"
style="float:left; vertical-align: middle;" />
<ice:commandLink value="Cancel" style="vertical-align: middle;"
actionListener="#{cfi.cancelEditCfiListener}" /></td>
</tr>
</ice:panelGroup>
</ui:repeat>
</tbody>
And this is the actionListener (in part):
public void editCfiListener(ActionEvent e) {
EvDetailBean evDetailBean = completeEvent.getEvDetailBean();
evDetailBean.setNewCFIName(this.getCfiName());
// initialize more fields
editThisOne = true; // This causes the row being edited to open up with modifiable fields.
}
Thanks in advance for your help.
Just check in your bean after submit if stringValue is "" and if so, set it to null and visible property to false.
the action , the bean function you are calling on click of edit button. inside that clear the stringValue variable.
Related
I want to change a div's class dynamically based on if an input value is true or false. Thought the function that validates the input is called the class is never changed. Here's the xhmtl:
<td>
<div class="#{regBean.nameclass}">
<h:inputText class="form-control input-sm" value="#{regBean.name}">
<f:ajax event="blur" listener="#{regBean.validateName}" render="namemsg" />
</h:inputText>
</div>
</td>
<td class="error">
<h:outputText class="error-msg" id="namemsg" value="#{regBean.nameMsg}"></h:outputText>
</td>
and here's the function from the according bean:
private static final String SUCCESS="form-group has-success";
private static final String ERROR="form-group has-error";
public void validateName(){
if(ValidatorUtilities.empty(name)){
nameMsg="Παρακαλώ εισάγετε όνομα!";
}
nameMsg=ValidatorUtilities.validateName(name);
if(nameMsg.equals("")){
nameclass=SUCCESS;
validations.put("name",true);
}
else{
nameclass=ERROR;
validations.put("name",false);
}
}
thought the message at element with id="namemsg" is correctly shown the class remains the same. Is there anything wrong or am I going for the wrong implementation and should do this client side by jquery?
Note:I've set the getter-setter for the string nameclass
Your code is not re-rendering the <div>. Your code is only re-rendering the <h:outputText>. I'm not sure why and how exactly you expected that the <div> is also covered by the re-rendering. All you need to so is to specify its client ID in the render attribute as well. You only need to replace <div> by <h:panelGroup layout="block">, because rendering can only target true JSF components.
<td>
<h:panelGroup id="field" layout="block" styleClass="#{regBean.nameclass}">
<h:inputText ...>
<f:ajax ... render="field namemsg" />
</h:inputText>
</h:panelGroup>
</td>
<td class="error">
<h:outputText id="namemsg" ... />
</td>
Unrelated to the concrete problem, your whole validation approach is utterly broken. You're supposed to use a true Validator and a <h:message>, exactly like as shown in every decent JSF book. This is also a strong hint that you still don't have one. I warmly recommend to work on that first.
See also:
How to create JSF form with AJAX data validation
How to perform validation in JSF, how to create a custom validator in JSF
i have initially 2 fields & submit after validating successfully diplays some more fileds with submit i have to validate these fields in server side
so first time i have used validate() for first time submitted second time i want to do server side validation.i have to do in single action ?
<s:form action="some.action" method="post" theme="simple" name="someForm" >
<td ><s:label value="StdNumber:" /></td>
<td ><s:textfield name="StdNum" theme="simple" /></td>
<td ><s:label value="Date of Birth:"/></td>
<td ><s:textfield size="10" name="dateOfBirth" id="dateOfBirth" onclick="displayCalendar(document.forms[0].dateOfBirth,'ddd-MM-yyyy',this)" />
<s:submit cssClass="button" value="Submit" name ="submitbtn" id="submitbtn" method="getEduInfo" /></td>
<s:if test="sucess">
<td ><s:textfield name="Stdname" theme="simple" /></td>
<td ><s:label value="marks:"/></td>
<td ><s:textfield size="10" name="marks" /></td>
<s:submit method="getPersonalInfo" value="submit"/>
</s:if>
</s:form>
To validate the fields differently you should get the name of the button .
In validate() you have to write as :
if(buttonName.equals(yourFirstButtonName)) {
/* validation code for first two fields*/
} else if(buttonName.equals(yourSecondButtonName)) {
/* validation code for second two fields */
}
You can get button name by giving name attribute to s:submit tag and write getters and setters to that name .
You can use annotated validations.
If we suppose, that you have 2 methods in your action class:
1) public String getEduInfo() {...}
2) public String getPersonalInfo() {...}
Just use #Validations annotation for each of them and place there appropriate validations.
Remember to set validateAnnotatedMethodOnly parameter on true for validation interceptor:
<interceptor-ref name="validation">
<param name="validateAnnotatedMethodOnly">true</param>
</interceptor>
Thanks to that, you can call different validation for different methods.
I have a 2 set of panel groups . one panel group contains a fieldset and inside, two radio buttons and one command button .Based on the selection of radio button, respected value will be displayed in another panel group through ajax call. But issue is after the radio button selection when the command button is clicked the other panel group is not at all rendered when the first time page loads . when i refresh everything works fine. I could not able to figure out why the renderedPanelGroup value is not set to true even that is being set in the command action .Here is my code.
test.xhtml
<h:form id="parentformid">
<h:panelGroup id="demandDashBoardPanelGroupID">
<fieldset>
<legend>Demand Dashboard</legend>
<table>
<tr>
<td>
<h:selectOneRadio id="groupbyid" value="#{demandManagedBean.selectedRadioButton}" >
<f:selectItem itemLabel="Group By Creation Date Time" itemValue="1" />
<f:selectItem itemLabel="Group By Location" itemValue="2" />
</h:selectOneRadio>
</td>
<td>
<h:commandButton id="fetchbuttonID" value="Fetch"
action="#{demandManagedBean.displayDemandRequestsTable}">
<f:ajax render=":parentformid:demandrequestpanelgrpid"execute="#form" />
</h:commandButton>
</td>
</tr>
</table>
</fieldset>
</h:panelGroup>
//For checking demandManagedBean.renderedPanelGroup value. it is giving always false.Thats why panel group is not getting rendered.
<h:outputText value="#{demandManagedBean.renderedPanelGroup}" />
<h:panelGroup id="demandrequestpanelgrpid" rendered="#{demandManagedBean.renderedPanelGroup}">
<fieldset id="demandrequestfieldsetid">
<legend >Demand Requests</legend>
<h:outputText rendered="#{demandManagedBean.renderFirstTable}" value="first table"/>
<h:outputText rendered="#{demandManagedBean.renderSecondTable}" value="second table"/>
</fieldset>
</h:panelGroup>
//Backing bean cmd action
private String selectedRadioButton ="1";
private boolean renderFirstTable ;
private boolean renderSecondTable;
private boolean renderedPanelGroup ;
//getter and setter methods
public void displayDemandRequestsTable(){
if(selectedRadioButton!= null && selectedRadioButton.endsWith("1")){
renderFirstTable = true;
renderSecondTable= false;
}else if(selectedRadioButton!= null && selectedRadioButton.endsWith("2")){
renderFirstTable = false;
renderSecondTable= true;
}
renderedPanelGroup = true;
}
You cannot update elements which are not rendered , rendered=false "is a JSF way to" to remove elements from the DOM Tree ,
its not like css display:none or visibility:hidden <- this two will keep the elements in the DOM tree but hidden , while the JSF rendered=false wont even render (keep) the element in the DOM tree (you wont even see it in the "view source" of the page)
So in you case you need to wrap the panelGroup with another `panelGroup' and update the id of the wrapper
<h:panelGroup id="demandrequestpanelgrpid">
<h:panelGroup rendered="#{demandManagedBean.renderedPanelGroup}">
.
.
.
also look at similar question
Can you update an h:outputLabel from a p:ajax listener?
I need to update the value of a textField, using a value on the server, based on the value the user chooses in a g:select. In code:
<g:select name="description" from="${momentum.MoneyTransType.prodList}" value="${moneyInstance?.description}"
noSelection="['':'-Select Description-']" onChange="${remoteFunction(action:'setHowMuch', update:[success:'howMuch', failure:'failure'],
params:'\'selection=\' + this.value', options=[asynchronous:false])}"/>
<g:textField id="howMuch" name="howMuch" value="${moneyInstance?.howMuch}"/>
It's not working. If I give the "update:[success:" a div id, all is good, but that's not what I want. I need to allow the user to enter in a free flow description (which I'll have in another textfield), and a free flow amount. I guess I could hide a div and then listen for changes to that div via jQuery, and then update the amount textField. Should I be able to update a textField using the remoteFunction "update" capability or using another grails capability?
Strangely, putting in a temporary 'toHide' div with a jQuery change function isn't working to update the textField, i.e. the following alert, etc, isn't firing:
$('#toHide').change(function() {
alert(" I got changed, value:");
$("#howMuch").text($(this).val());
});
Well, after writing all the below, I reread your question and see you stated you know it works with a div. So the rest of my answer might not be helpful, but what's wrong with using a div? An empty div won't display anything, so you don't need to hide it. So FWIW:
Put your <g:textField ...> in a template.
Add a div where where you want the template to be rendered. In other
words, replace the current <g:textField ..> with <div id=updateme name=updateme></div>
In your setHowMuch action, render the template.
For example, I do:
In view:
<g:select class='setTagtypeValue-class'
name='tagtype-${i}-header'
from="${org.maflt.ibidem.Tagtype.list(sort:'tagtype').groupBy{it.tagtype}.keySet()}"
value="${setTagtypeValue?.tagtype?.tagtype}"
valueMessagePrefix="tagtype"
noSelection="${['null':'Select One...']}"
onchange="${remoteFunction(action:'options', update:'tagtype-options-${i}',
params:'\'tagtype=\' + this.value +\'&i=${i}\'' )}" />
Controller action:
def options = {
def i = params.i ?: 0
def tagtypes = Tagtype.findAllByTagtype(params.tagtype)
render(template:"tagtypeList", model:[tagtypes:tagtypes,i:i])
}
tagypeList Template:
<table>
<tr>
<th></th>
<th><g:message code="tagtype.lookup"
default="Lookup Table" /></th>
<th><g:message code="tagtype.regexpression"
default="Field Rule" /></th>
<th><g:message code="tagtype.uicomponent"
default="UI Component" /></th>
</tr>
<g:each in="${tagtypes}" var="tagtype" status="j">
<tr>
<td><g:radio name="setTagtypesList[${i}].tagtype.id" value="${tagtype.id}"
checked="${(setTagtypeValue?.tagtype?.id == tagtype.id ||
(!setTagtypeValue?.tagtype?.id && j==0))}"></g:radio></td>
<td>${tagtype.lookupTable}</td>
<td>${tagtype.regexpression}</td>
<td><g:message code="${'uicomponent.' + tagtype.uicomponent.id}"
default="${tagtype.uicomponent.uicomponent}" />
</td>
</tr>
</g:each>
</table>
This code is from the metadataset (called field set in the UI) screen in http://www.maflt.org/products/Ibidem.
I'm upgrading from JSF 1.2 to JSF 2 and Richfaces 3.3 to 4.
I've tried various version of JSF2 (2.02, 2.06, etc) and all give the same error.
I'm getting the following error that has been hurting my head for hours now!
SEVERE: Error Rendering View[/my-testfile.xhtml]
javax.el.PropertyNotFoundException: /templates/components-navigation.xhtml #31,54 rendered="#{component.allowed}": Property 'allowed' not found on type org.richfaces.component.UIRepeat
/templates/components-navigation.xhtml
<a4j:outputPanel rendered="#{loginBean.loggedIn}">
<a4j:repeat var="menugroup" value="#{componentNavigator.groups}">
<a4j:region rendered="#{menugroup.itemCount > 0}">
<div class="panel_menu">
<table class="title" border="0" width="100%">
<tr>
<td>
<h:outputText class="text" value="#{messages[menugroup.id]}" />
</td>
</tr>
</table>
<table class="links" border="0" width="100%">
<tbody>
<a4j:repeat var="component" value="#{componentNavigator.components}">
<a4j:region rendered="#{component.allowed}">
<a4j:region rendered="#{component.groupId == menugroup.id}">
<tr class="#{component.current?'active':'unactive'}">
<td> </td>
<td class="text" width="100%">
<h:commandLink action="#{component.getCommandAction}" actionListener="#{componentNavigator.initControllerBean}">
<span style="display:block;">
#{messages[component.id]}
</span>
<f:attribute name="controllerBean" value="#{component.controllerBean}" />
<f:setPropertyActionListener target="#{componentNavigator.currentComponent}" value="#{component}" />
</h:commandLink>
</td>
</tr>
</a4j:region>
</a4j:region>
</a4j:repeat>
</tbody>
</table>
</div>
</a4j:region>
</a4j:repeat>
</a4j:outputPanel>
Line 31 is:
<a4j:region rendered="#{component.allowed}">
Any ideas why the property is not been found? Is there a know issue with the repeat component?
#{component} is a reserved and implicit EL object which refers to the current JSF component. It can be used as follows:
<h:inputText value="#{bean.value}" styleClass="#{component.valid ? 'ok' : 'error'}" />
In the above example, the #{component} resolves to an UIInput instance representing the current <h:inputText>, which in turn has a isValid() method. Upon submit, when the component has a validation error, the error style class will be set (which may have for example a reddish background color), else the ok style class will be set. It's like as this in JavaScript.
You should give your scoped variables a different name. Do not use the name of one of the following reserved EL objects in JSF:
#{component} - the current UIComponent
#{facesContext} - the current FacesContext
#{request} - the current HttpServletRequest
#{session} - the current HttpSession
#{application} - the ServletContext
#{cc} - the current composite component
#{param} - the current request parameter map
#{paramValues} - the current request parameter values map
#{requestScope} - the current request attribute map
#{viewScope} - the current view attribute map
#{sessionScope} - the current session attribute map
#{applicationScope} - the application attribute map
#{header} - the current request header map
#{cookie} - the current request cookie map
Your 'component' bean needs a
public boolean getAllowed() {
return this.allowed;
}
and
public void setAllowed(boolean allowed) {
this.allowed = allowed;
}
method. A property is a field in your bean, which needs a public getter and setter method. Most IDEs support generating those methods look out for something like "Source --> Generate Getter and Setter".
Another possibility would be to call a method directly. Something like,
<a4j:region rendered="#{component.isAllowed()}">
with a bean code
public boolean isAllowed() {
return this.allowed;
}
If you've already getter and setter in your componentNavigator bean it would be usefull if you could post it here (or parts of it).
Richard
I changed:
<a4j:repeat var="component" value="#{componentNavigator.components}">
to:
<a4j:repeat var="myComponent" value="#{componentNavigator.components}">
and it's all good now :)
I stumbled across this issue which gave me the clue:
https://issues.jboss.org/browse/RF-8026