I am trying to get the value contained in a value expression. I need to use it for some validation. When I set the value expression in an HTMLOutput it is displayed on the screen. Please suggest what am I doing wrong?
HtmlOutputText output = new HtmlOutputText();
ve = ef.createValueExpression(elCtx, "#{dynamicRow["+ i + "]}", String.class);
//I have tried all options here that I came across.
//Either test1 , test2 , test3 should have the value ve has, but all of them have value "".
String test1 = (String)ve.getValue(elCtx);
String test2 = (String)output.getValue();
Application app = fCtx.getApplication( );
String test3 = (String) app.evaluateExpressionGet(fCtx, "#{dynamicRow["+ i + "]}", String.class);
output.setValueExpression("value", ve);
//the ve gets displayed in the column with correct string values and not ""
column.getChildren().add(output);
// I also tried ValueReference as given in ValueExpression: how to get base Object?
ValueReference valueReference = ve.getValueReference(elCtx);
//an exception is thrown here javax.el.PropertyNotFoundException: Target Unreachable, identifier 'dynamicRow' resolved to null
Object base = valueReference.getBase();
Object property = valueReference.getProperty();
where my table has the following code:
FacesContext fCtx = FacesContext.getCurrentInstance();
ELContext elCtx = fCtx.getELContext();
ExpressionFactory ef = fCtx.getApplication().getExpressionFactory();
HtmlExtendedDataTable dynamicDataTable = new HtmlExtendedDataTable();
HtmlDatascroller datascroller = new HtmlDatascroller();
ValueExpression ve = ef.createValueExpression(elCtx,"#{myController.dynamicList}", List.class);
dynamicDataTable.setValueExpression("value", ve);
dynamicDataTable.setVar("dynamicRow");
The var value dynamicRow is only in scope when the table places it into scope during processing. This is done by the various process* methods on component.
See setRowIndex(int) documentation:
Save current state information for all descendant components (as described below).
Store the new row index, and pass it on to the DataModel associated with this UIData instance.
If the new rowIndex value is -1:
If the var property is not null, remove the corresponding request scope attribute (if any).
Reset the state information for all descendant components (as described below).
If the new rowIndex value is not -1:
If the var property is not null, call getRowData() and expose the resulting data object as a request scope attribute whose key is
the var property value.
Reset the state information for all descendant components (as described below).
Related
FacesContext context = FacesContext.getCurrentInstance();
ELContext ctx = context.getELContext();
ValueExpression expression = context.getApplication().getExpressionFactory().createValueExpression(
ctx, "#{foo111.bar}", String.class);
String value = expression.getValue(ctx);
The return value is null. Obviously foo111.bar does not exist. Is there a way to tell if an expression does not exist or actually its value is null.
The best way to do that would be to evaluate the expression. If it's a property expression this should be side-effect free (And smart EL Implementations cache this operation, so it should be cheap if invoked several times).
If it's a method expression it'll get more complicated. Invoking the function could cause a state mutation if all you're wanting to do is 'check for existence'. You could in theory get the base object and see if it exists without invoking the function, which gets you a little closer, but isn't a complete solution:
final ValueReference valueReference = valueExpression.getValueReference(getFacesContext().getELContext());
final Object base = valueReference.getBase();
... valueReference.getProperty();
I have a data table with a POJO object:
<p:dataTable id="table" var="object" sortBy="#{object.name}" sortOrder="DESCENDING">
object has fields id, name, date, size for example. I am able to set default sort field using xhtml, but I want set it from backing bean.
I am able to parse column id when user creates sort request for example name.
public void sortEventListener(AjaxBehaviorEvent actionEvent) {
String id = ((SortEvent) actionEvent).getSortColumn().getColumnKey();
String[] idPath = id.split(":");
sortBy = idPath[idPath.length - 1];
sortOrder = ((SortEvent) actionEvent).isAscending();
}
My task detects which column user wants to sort and persists it to db. After reload the data table should be sorted by this column.
When I set
sortBy="#{bean.sortBy}" // sortBy = name
it's not working and data table is not sorted after rendering the page.
Please help.
If you bind your data table to a org.primefaces.component.datatable.DataTable object in your bean or find the table component in your bean, you can use the table object to set the sortBy value expression programmatically.
To get an idea how PrimeFaces is handling sorting, you can have a look at the source code at GitHub.
When you have the sort column, you can easily get the sort value expression. So, in your listener you could use something like:
UIColumn sortColumn = sortEvent.getSortColumn();
ValueExpression sortByVE = sortColumn.getValueExpression("sortBy");
By the way, you can replace the parameter type AjaxBehaviorEvent with SortEvent in your sort listener method.
Now, store the sortByVE expression, and set it as the sortBy value expression of the bound table when needed:
dataTable.setValueExpression("sortBy", sortByVE);
If you want to create the value expression from scratch, use something like:
FacesContext context = FacesContext.getCurrentInstance();
ExpressionFactory ef = context.getApplication().getExpressionFactory();
ValueExpression ve = ef.createValueExpression(context.getELContext(),
"#{object.name}",
Object.class);
dataTable.setValueExpression("sortBy", ve);
In this example "#{object.name}" is fixed. You should construct it based on the value you get from your sort listener.
If you want to find your table in your bean, OmniFaces Components might be helpful. It also offers a shortcut method to create value expressions.
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?
Programmatically getting UIComponents of a JSF view in bean's constructor
How do I set the value of HtmlOutputTag in JSF?
I have a task flow with two AMX pages.
First page has a selectOneChoice (Product list) which is created from data control (having allProducts(a ArrayList of a ProductPOJO class)).
I dragged and drop allProducts from my dataControl to AMX page. and got code as-
<amx:selectOneChoice value="#{bindings.allProducts.inputValue}" label="Products" id="soc1"
valueChangeListener="#{pageFlowScope.lcBean.onProductChange}">
<amx:selectItems value="#{bindings.allProducts.items}" id="si1"/>
</amx:selectOneChoice>
and set a method onProductChange(ValueChangeEvent valueChangeEvent) inside a bean class where i am getting the selected row from selectOneChoice and doing further operation.
public void onProductChange(ValueChangeEvent valueChangeEvent) {
AmxAttributeBinding productList =
(AmxAttributeBinding) AdfmfJavaUtilities.evaluateELExpression("#{bindings.allProducts}");
AmxIteratorBinding amxListIterator = productList.getIteratorBinding();
BasicIterator basicIterator = amxListIterator.getIterator();
ProductPOJO currentProduct = (ProductPOJO) basicIterator.getDataProvider();
System.out.println("InSide onProductChange"+currentProduct.getProduct());
ValueExpression ve;
ve = AdfmfJavaUtilities.getValueExpression("#{pageFlowScope.nupMinimumsFlag}", Integer.class);
ve.setValue(AdfmfJavaUtilities.getAdfELContext(), currentProduct.getNupMinimumsFlag());
ve = AdfmfJavaUtilities.getValueExpression("#{pageFlowScope.productFlag}", Integer.class);
ve.setValue(AdfmfJavaUtilities.getAdfELContext(), currentProduct.getProductFlag());
ve = AdfmfJavaUtilities.getValueExpression("#{pageFlowScope.product}", String.class);
ve.setValue(AdfmfJavaUtilities.getAdfELContext(), currentProduct.getProduct());
}
Issue is :- when we select some value in selectOneChoice and then click on submit to go to next page. and then coming back to first page. Value of selectOneChoice is getting reset to default value(first value from collection). Its not able to cache the old(selected) value.
The working behaviour of select one choice is different on Oracle MAF. It is not able to cache the Object.
In first approach I was trying to cache an object.
To cache value on selectOneChoice we will have to get the index of selected choice and save it in your datacontrol class.
I got it fixed as below.
AMX Code :-
<amx:selectOneChoice value="#{bindings.selectedProduct.inputValue}" label="Products" id="soc1"
valueChangeListener="#{bindings.onProductChange.execute}" required="true"
showRequired="true">
<amx:selectItems value="#{bindings.allPoroducts.items}" id="si1"/>
</amx:selectOneChoice>
Java Code :-
public void onProductChange() {
System.out.println("InSide onProductChange" + selectedProduct);
ProductPOJO currentProduct = allPoroducts.get(Integer.parseInt(selectedProduct));
System.out.println("InSide onProductChange" + currentProduct.getProduct());
ValueExpression ve = AdfmfJavaUtilities.getValueExpression("#{pageFlowScope.nupMinimumsFlag}", Integer.class);
ve.setValue(AdfmfJavaUtilities.getAdfELContext(), currentProduct.getNupMinimumsFlag());
ve = AdfmfJavaUtilities.getValueExpression("#{pageFlowScope.productFlag}", Integer.class);
ve.setValue(AdfmfJavaUtilities.getAdfELContext(), currentProduct.getProductFlag());
ve = AdfmfJavaUtilities.getValueExpression("#{pageFlowScope.product}", String.class);
ve.setValue(AdfmfJavaUtilities.getAdfELContext(), currentProduct.getProduct());
}
where 'private String selectedProduct;' is a string type object. so when we will select or change value on selectonechoice it will return numbers in string format like(0, 1, 2, 3, 4, 5 basically index values). which we will convert it to int and will get the value from product array with that index.
I have an Xpages application that manipulates Contracts. One procedure uses the Contract Type value in field "conService" to determine what must happen next. The code below does NOT produce any errors but third line does not seem to process any result and in fact does not even seem to process any line in the procedure after it. How do I extract the value of the conService? Thanks
UIInput uifield = (UIInput) JSFUtil.findComponent("conService");
String serviceName ="";
serviceName = uifield.getValue().toString();
You are almost there....
Once you have the UIInput object you can do either .getSubmittedValue() or .getValue() - depending on where in the JSF lifecycle you are. And then you just need to cast it to a String - instead of using toString().
So something like should do the trick:
UIInput uifield = (UIInput) JSFUtil.findComponent("conService");
String serviceName = (String)uifield.getValue();
To avoid having to thinkg about using getSubmittedValue or getValue I use a small utility method in my code:
ublic static Object getSubmittedValue(UIComponent c) {
// value submitted from the browser
Object o = null;
if (null != c) {
o = ((UIInput) c).getSubmittedValue();
if (null == o) {
// else not yet submitted
o = ((UIInput) c).getValue();
}
}
return o;
}
That just makes life a little less complicated ;-)
/John
Where possible, it's worth going directly to the datasource you're storing the value in. It's more efficient and easier to manage.
If you do need the value during Process Validation phase, for a converter or validator, you can use component binding to easily access the relevant component, at which point you can use getSubmittedValue() - because the value will not have been set yet. Here's a NotesIn9 from Tim Tripcony covering it http://notesin9.com/index.php/2014/05/22/notesin9-143-component-vs-value-binding-in-xpages/.
I need to call ssjs from a java bean similar to this this issue. The issue is that the code I need to execute comes from a configuration document, and may look like:
getComponent("xxx").getValue();
I have built a version that does :
String compute = doc.getItemValueString("SSJSStuff");
String valueExpr = "#{javascript:" + compute + "}";
FacesContext fc = FacesContext.getCurrentInstance();
Application app = fc.getApplication();
ValueBinding vb = app.createValueBinding(valueExpr);
String vreslt = vb.getValue(fc).toString();
but I get "Exception in xxx: com.ibm.xsp.exception.EvaluationExceptionEx: Error while executing JavaScript computed expression"
I think I am close, but I do not see over the hill.. Any thoughts?
There are several possibilities for this:
The variable compute is empty
compute contains illegal chars
The code inside compute is malformed / has no correct syntax
No object is returned in your SSJS code:
If your SSJS code does not return something, vb.getValue(fc) returns null. A toString() will fail. To prevent this, you should cast your returning object explicitly:
vreslt = (String) vb.getValue(fc);
Hope this helps
Sven
EDIT:
After re-reading your post, I saw that you want to do a getComponent in your dynamic SSJS Code. This won't work with a value binding added to the javax.faces.application.Application. For this, you have to use the com.ibm.xsp.page.compiled.ExpressionEvaluatorImpl object instead:
String valueExpr = "#{javascript:" + compute + "}";
FacesContext fc = FacesContext.getCurrentInstance();
ExpressionEvaluatorImpl evaluator = new ExpressionEvaluatorImpl( fc );
ValueBinding vb = evaluator.createValueBinding( fc.getViewRoot(), valueExpr, null, null);
vreslt = (String) vb.getValue(fc);