JSF binding with setValueExpression read-only? - jsf

I try to create an InputField in the backing bean and add it to the view, but the databinding seems to work just read-only.
I create a UIInput in the Backing-Bean like this:
UIComponent textInput = new UIInput();
textInput.setId("operandInputText");
textInput.setValueExpression("value", ef.createValueExpression(elCtx, "#{row.operandValues[0]}", String.class));
textInput.setValueExpression("rendered", ef.createValueExpression(elCtx, "#{row.inputType == 'text'}", Boolean.class));
mInputPanelGroup.getChildren().add(textInput);
The panelGroup is inside a column of a dataTable and bound to the bean:
<p:column id="operandColumn">
<h:panelGroup id="inputPanelGroup" binding="#{locateEmployeeBean.inputPanelGroup}" >
<h:inputText id="testInput" value="#{row.operandValues[0]}" />
</h:panelGroup>
</p:column>
The <h:inputText/> inside the PanelGroup is just for testing and this is where I found out that the binding I did with setValueExpression(...) works at least read-only.
In the browser I now have 2 inputFields, first the 'testInput' and then 'operandInputText'.
When I enter a value in 'operandInputText' and submit, the value does not get saved, but when I enter a value in the 'testInput'-Field, it get's submitted and in addition the value gets displayed in BOTH inputFields.
The operandValues is a simpe object array:
private Object[] mOperandValues = new Object[2];
Could this have anything to do with the dataType I pass to setValueExpression(...)?
I tried Object, but that didn't change anything.
Any idea why this happens?
Thanks in advance!

I found the solution to my problem. Honestly it was an article by #BalusC Using Datatables: Populate datatable what took me on the right path.
Previously I added the components during PreRenderView-Phase, then I saw in your example that you populate the bound component ONCE in the getter (which is then obviously way earlier during RestoreView-Phase). That is how I've done it now and it works flawlessly, the Inputfields now work both ways (read+write).
Thanks alot for your work #BalusC!

Related

Get row number in p:dataTable of dynamic element

I'm curious about how to get the row number of an element inside the <p:dataTable>.
<p:dataTable id="userDataTable" value="#{bean.rows}" rowIndexVar="rowIndex">
<p:column headerText="RowCounter">
<p:commandLink id="row#{rowIndex+1}" actionListener="#{bean.getRows}">
<h:outputText value="Show Row #{rowIndex+1}" />
</p:commandLink>
</p:column>
</p:dataTable>
Bean:
public void getRows(ActionEvent ae) {
System.out.println(ae.getComponent().getId().toString());
}
Always prints row1, no matter which <p:commandLink> is clicked. What am I missing?
As to your concrete problem, the id attribtue of a JSF component is evaluated during view build time. However, the #{rowIndex} is only set during view render time. Thus, at the moment the id attribute is evaluated, the #{rowIndex} is nowhere been set and defaults to 0. This problem has essentially exactly the same grounds as already answered and explained here: JSTL in JSF2 Facelets... makes sense? Note thus that there's only one <p:commandLink> component, not multiple. It's just that it's been reused multiple times during generating HTML (everytime with the same component ID!).
To fix it, just use id="row" instead. The dynamic ID makes no sense in this particular case. JSF would already automaticlaly prepend the row index (check generated HTML output to see it). I'm not sure why exactly you incorrectly thought that you need to manually specify the row index here, so it's hard to propose the right solution as there are chances that you actually don't need it at all. See also How can I pass selected row to commandLink inside dataTable?
For the case you really need the row index, here's how you could obtain it:
Integer rowIndex = (Integer) ae.getComponent().getNamingContainer().getAttributes().get("rowIndex");
The UIComponent#getNamingContainer() returns the closest naming container parent which is in your particular case the data table itself, in flavor or UIData which in turn has thus the rowIndex property. You can alternatively also do so, which is a bit more self documenting:
UICommand commandLink = (UICommand) ae.getComponent();
UIData dataTable = (UIData) commandLink.getNamingContainer();
Integer rowIndex = dataTable.getRowIndex();

jsf inputtext doesn't show value from bean

I have the follow situation:
I have a bean that send to form some data, but only in outputlabel the data from the bean is displayed.
I tried to use primefaces, but the same problems persist.
my code:
<h:outputLabel value="#{Bean.name}" id="name2" />
<h:inputText value="#{Bean.name}" id="name" />
<p:inputText value="#{Bean.name}" id="name3" />
Any idea why?
You should have given the bean's code also, to help us better analyze the problem.
Normally you should check for the following:
Check whether you are specifying a correct bean name. Normally
bean's name is same as that of class, except that first letter
should be lowercase. In your case it should be #{bean.name} or else,
specify your custom name with #Named("Bean").
Check whether the getters and setters such as getName() are properly
provided. It may happen that you might have reset the name property in
your bean in the get method itself. Because of which first time it
shows you properly in outputLabel and then in next call to getName it may give you null or empty String. To check this, try put your inputText tag first, and check.
I solve my problem.
When I tried show the values, I was trying recover data from database by pass an ajax action. So, When I clicked at button to retrieve the datas, some of my inputText were set as a required. And because this the data is just displaying into label and not inside of inputtext with required. But because ajax, the request were not called correctly.
When I remove the required from inputtext, it works fine.

Valuechangelistener Doubt in JSF

HI,
Please see the following code:
<h:selectOneMenu id="countries" value="#{countryBean.selectedCountry}" onchange="submit()
valueChangeListener="#{countryBean.changeCountry}">
<f:selectItems value="#{countryBean.countries }" />
</h:selectOneMenu>
Backing Bean
public void changeCountry(ValueChangeEvent event){
String newValue = (String)event.getNewValue();
String oldValue = (String)event.getOldValue();
System.out.println("New Value : " + newValue);
System.out.println("Old Value : " + oldValue);
if ("1".equals(newValue)){
this.countries = new ArrayList<SelectItem>();
this.cities.add(new SelectItem("1","Delhi"));
this.cities.add(new SelectItem("2","Mumbai"));
}
if ("2".equals(newValue)){
this.cities = new ArrayList<SelectItem>();
this.cities.add(new SelectItem("1","Mossco"));
}
}
Please let me know if the implementation is correct. It is working fine.
My questions are:
What is the advantage of adding the f:valueChangeListener tag inside the h:selectOneMenu tag. I have used the normal attribute valueChangeListener="#{countryBean.changeCountry}".
Is it necessary to use onchange="submit() this code to change the values.
What is difference between writing the custom listeners by implementing the ActionListener interface and just using the attribute in the UIComponent tags (action="methodName").
Please explain me.
The ValueChangeListener will only be called when the form is submitted, not when the value of the input is changed. Thus, if you want to run this listener when the value is modified, you have two solutions:
Submit your form when the onchange event is fired (this is what you did in your code);
Use an Ajax call instead, by using some dedicated components (already integrated in JSF2, with <f:ajax>, or third-parties libraries such as Richfaces, Primefaces...).
Here is an example with Richfaces:
<h:selectOneMenu id="countries" value="#{countryBean.selectedCountry}" valueChangeListener="#{countryBean.changeCountry}">
<a4j:support event="onchange" .../>
<f:selectItems value="#{countryBean.countries }" />
</h:selectOneMenu>
Regarding the code of your listener, it seems correct, but why question is why do you need a ValueChangeListener here? Indeed, this listener is usefull when you want to track a modification of a value. That's why the ValueChangeEvent provides both getOldValue() and getNewValue() methods.
In your code, you do not care about the old value, so basically, you could "simply" do an action instead of a valueChangeListener (ex. with Richfaces):
<h:selectOneMenu id="countries" value="#{countryBean.selectedCountry}">
<a4j:support event="onchange" actionListener="#{countryBean.changeCountry}"/>
<f:selectItems value="#{countryBean.countries }" />
</h:selectOneMenu>
Finally, regarding the difference between the valueChangeListener attribute and <f:valueChangeListener> is that the first binds a Java method (#{myBean.myMethod}), while the second binds a Java class (type="com.foo.MyListenerClass") which implements the ValueChangeListener interface. So the second one could be more generic than the first one...
Romaintaz already pointed out the most, I just wanted to get straight on your concrete questions:
What is the advantage of adding the f:valueChangeListener tag inside the h:selectOneMenu tag. I have used the normal attribute valueChangeListener="#{countryBean.changeCountry}".
As Romaintaz said, the attribute points to a method and the f: tag points to a class. Another advantage is that you can have multiple of them, whenever that is necessary.
Is it necessary to use onchange="submit() this code to change the values.
That Javascript doesn't change the values. That Javascript submits the entire form without the need to pressing the submit button yourself, whenever the value has been changed by the enduser. No, that is not necessary. You can also just remove it and expect that the enduser presses the submit button himself. Once again, that JavaScript is not part of JSF.
What is difference between writing the custom listeners by implementing the ActionListener interface and just using the attribute in the UIComponent tags (action="methodName").
This question is already asked before: difference between action and actionlistener.
The solution from romaintaz of calling an action instead of valueChangeListener is also great because in the case of "change" event the action is called after the model is updated (allowing for a DB update for example) while the valueChangeListener is called before....

JSF selectOneMenu is refreshing and going back to its previous state rather than showing the new value

I have a datatable where a lot of selectOneMenu items are available , for example, for 10 items each having one selectOneMenu combo. now if i click on any of the combos, they are supposed to save the value in the database and they do it. but after saving the changed value the selectOneMenu is returning back to its previous state. I want the selectOneMenu to keep its current state. also, the method is being invoked for every single combo in the datatable. i really wonder why!! i have been banging my head for the last 2 weeks. any help would be really appreciated. thanks in advance.
this is my first post here. this is my jsf datatable:
<h:dataTable value="#{careNeedBean.controlledCareNeedsList}" var="careNeed"
id="careneed_table" binding="#{careNeedBean.dataTable}">
<h:column>
<f:facet name="header">
<h:outputText value="NeedsLevel"/>
</f:facet>
<h:selectOneMenu id="needs_level_combo" style="width:200px;font-size:9px;"
onchange="submit()"
valueChangeListener="#{careNeedBean.saveTaskAsessment}"
binding="#{careNeedBean.selectOneMenu}">
<f:selectItem itemValue="not_assessed" itemLabel="----Not assessed----"/>
<f:selectItems value="#{careNeed.humanReadableNeedsList}" />
</h:selectOneMenu>
</h:column>
This is my bean code:
public String saveTaskAsessment(ValueChangeEvent event) {
//does some things
return "Success";
}
The valueChangeListener doesn't run on the recently changed component only. In fact, you're using JavaScript submit() function to submit the entire form. The valueChangeListener will always be executed whenever the new selected value differs from the old value as is been declared in the value attribute.
You don't have declared a value attribute, so its default value is effectively null. If the default selected item of the list is not null, then the valueChangeListener will be invoked.
To fix this, you need to assign a value attribute to the component
<h:selectOneMenu value="#{careNeed.needsLevel}">
and you need to prefill it with the same value as the default value of the dropdown list.
this.needsLevel = "not_assessed";
Alternatively, you can also make the default value null.
<f:selectItem itemValue="${null}" itemLabel="----Not assessed----"/>
Unrelated to the problem, since you're already on JSF 2.0, I'd suggest to use <f:ajax> to submit only the recently changed dropdown by ajaxical powers instead of using onchange="submit()" to submit the entire form. That's after all better for user experience.
<h:selectOneMenu>
<f:ajax />
</h:selectOneMenu>
Also, the valueChangeListener method doesn't need to return anything. It will be ignored anyway. Just declare it void.
You can use AjaxSingle="true" and onsubmit="form.refresh();" on your ajax request.
So that it will process only the current component.
form.refresh(); will remove the old cache value.
You will get the refreshed bean value.

Why is a dynamic created JSF EL value expression not resolved?

I got a simple setup (and a big issue): a JSP page with en empty panel grid item container and a binding to a bean.
<h:panelGrid binding="#{ bean.container }" id="container" />
When the getter of the bean will be called, the container is filled with a random number of columns with a command link inside. So far so good. The container is filled up with the right number of elements, and with the use of an ActionListener on the links, I get all click events.
Here comes the tricky part: I want to mark the 'selected' or 'pressed' column via a different style class. With a static setup, I would do this with an expression like:
<h:column styleClass="#{ bean.selectedColumn eq 'id' ? 'btnSelected' : 'btn' }">
<!-- command link and some blahblah -->
</h:column>
The bean contains a simple getter getSelectedColumn() , that returns an id. Straight forward, so this works perfect!
But when I try to do the same inside the bean,
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
String expression = "#{ bean.selectedColumn eq 'id' ? 'btnSelected' : 'btn' }";
new ExpressionFactoryImpl().createValueExpression(elContext, expression, String.class);
column.setValueExpression("styleClass", valueExpression);
the expression won't ever be resolved. To make myself clear: both the command links, the columns and the value expressions are generated inside the bean. Is that the cause?
Can anyone tell me why? Thanks in advance!
When the JSP is compiled the bean wont be called! This is done at runtime cause you want to see live data in the bean. Therefore the (later) generated EL is not visible at compilation. The EL would not be resolved at runtime.

Resources