Expression Language equivalent of getComponent() - xpages

I couldn't find it anywhere only about the equivalent in java but does anyone know what the EL equivalent is of getComponent("name").value?

It's whatever the component is bound to... so if your page includes:
<xp:inputText value="#{currentDocument.subject}" />
...then this will display the same result:
<xp:text value="#{currentDocument.subject}" />
You can also reference the value using any of the standard EL operators; e.g.:
<xp:label rendered="#{not(empty(currentDocument.subject))}" ...>
<xp:comboBox rendered="#{currentDocument.totalAmount gt 1000}" ...>
<xp:panel rendered="#{currentDocument.optIn eq 'Yes'}" ...>
And EL also support "associative array" syntax, which is handy when needing to refer either to dynamically named properties, or properties that are editable outside a Custom Control but you need to reference them inside a Custom Control. For instance, if you define dataSource and propertyName as custom properties for your Custom Control, you could pass them in from a context that "knows" what they are:
<xc:dynamicLabel dataSource="currentDocument" propertyName="subject" />
...then reference them inside that Custom Control:
<xp:label text="#{compositeData.dataSource[compositeData.propertyName]}" />
And, of course, all of this works with any of the types that the XPages engine knows how to reference via EL:
SSJS objects
Java Maps (i.e. scope variables)
Instances of DataObject (standard Domino document data sources, custom implementations, etc.)
Any valid Java bean (adheres to bean conventions)
To be precise, when EL is interpreted, the variable resolver checks to see if it's one of the first three, and if it is, evaluates any properties in a manner specific to that type. If it isn't one of those first three, it assumes it's a bean.
To sum up, any given component doesn't "know" its own value. If you programmatically get a handle on a component and call its getValue method, that method checks to see if its value is a value binding (EL, SSJS, etc.). If it is, then it evaluates that expression and returns the result. So if you need that same result elsewhere, just use the same expression in the alternate location as well, because it will return the same result...... just don't bind the value attribute of multiple editable components to the same expression; that can produce unpredictable results.

Related

What exactly is #{component} in EL?

According to https://code.google.com/p/primefaces/issues/detail?id=4720, The ComponentUtils.resolveWidgetVar(String expression, UIComponent component) function is available in Primefaces since 2013. It can be used in EL by the "#{p:widgetVarFromContext(searchExpression, component)}" function.
This is useful in case of several components have the same id in different NamingContainer, but are still present in the same view. In this case,
the #{p:widgetVar(searchExpression)} function only returns the last one found.
I don't understand however how to reference the UIComponent that must be passed as the second argument from EL. The above mentioned bug report suggests we can refer to it using #{component}. Can anyone provide me with an example?
The #{component} is an implicit EL variable referring the current UIComponent in EL scope (see also implicit EL objects). You can usually only refer it in component's HTML attribute or in template text children.
E.g. in case of <h:inputText> it will reference an instance of UIInput class which has among others an isValid() method.
<h:inputText id="foo" required="true"
style="background: #{component.valid ? '' : 'pink'}"
onclick="alert('Client ID of this component is #{component.clientId}');" />
You can also use binding attribute to let JSF during view build time put a reference to a component instance in the Facelet scope. This way the component reference will be available anywhere in the Facelet during view render time.
<script>alert('Client ID of foo component is #{foo.clientId}');</script>
<h:inputText binding="#{foo}" />
See also:
Difference between client id generated by component.clientId and p:component()
JSF component binding without bean property
How does the 'binding' attribute work in JSF? When and how should it be used?
The p:widgetVarFromContext is useful when referring to a PrimeFaces widget inside a composite component. There could be more than one instance of your component on the same page. So writing widgetVar="expression" and PF('expression') is out of the question. There would be multiple widgets with the same name. It is then better to omit the widgetVar attribute and use the generated one which is unique because it is based on the clientId.
You can't use #{p:widgetVar('expression')} within your <cc:implementation> because it leads to a Cannot find component for expression "expression" referenced from "j_id1" error instead of the expected PF('widget_expression').
But you can use #{p:widgetVarFromContext('expression', cc)} which will return something like PF('widget_wrapperform_compositecomponent1_expression'). The cc refers to the root of the composite component instance.

Choosing between composite components inside ui:repeat

I have something like <ui:repeat value="#{list}" var="a" /> where list is of type List<Action> and contains various objects that extend Action. Depending on the actual type of Action, I want to render a different composite component (for example, for ActionA I want to render component A and for ActionB I want to render B, where B would throw an exception if it were to get a value of type ActionA). How can I do this? It seems that using rendered="#{a.type == 'ACTION_A'}" (where type is a property of Action) on the composite components doesn't work as each iteration of ui:repeat adds all components to the tree so it sends the value a to each composite.
Thank you.

How to implement foreach in jsf?

How do I create ofer_has_location objects (join object from location and ofer) using the current ofer and the selected items from the h:selectManyCheckBox
<h:selectOneMenu id="companyidCompany"
value="#{oferController.selected.companyidCompany}"
title="#{bundle.CreateOferTitle_companyidCompany}"
required="true"
requiredMessage="#{bundle.CreateOferRequiredMessage_companyidCompany}">
<f:ajax event="valueChange" execute="companyidCompany"
render="locationCollection" />
<f:selectItems value="#{companyController.itemsAvailableSelectOne}"/>
</h:selectOneMenu>
<h:outputLabel value="#{bundle.CreateOferLabel_locationCollection}"
for="locationCollection" />
<h:selectManyListbox id="locationCollection" value="locations"
title="#{bundle.CreateOferTitle_locationCollection}">
<c:forEach items="locations">
<f:selectItems var="locations"
value="#{oferController.selected.companyidCompany.locationCollection}" />
</c:forEach>
</h:selectManyListbox>
What you need to do in order to achieve 'connected elements' functionality:
Have two elements ( <h:selectOneMenu> and <h:selectManyLisBox> in your case), where the second one will be dependent on the selected option(s) of the first one. The second element must have an id in order to be rerendered afterwards.
Every HTML select element (that's rendered by both JSF tags of your choice) will have a set of options that are not supposed to be created via iterative element like <c:forEach> (though, it is in fact possible), but rather via the <f:selectItem>/<f:selectItems> tags (thus, remove your iterative tag in comment).
When values in the components are bound not as plain Strings, or primitive wrappers (Integer, etc.), but rather as model objects (YourClass objects, etc.), then you need to tell JSF two things: how can it print option's value from your class and how can it reconstruct an object from request parameter that is a string. For this you need to implement Converter, that is, explain JSF how to do the abovementioned transformations. Use this answer and BalusC's blog as reference points. Note the appropriate syntax for <f:selectItems itemValue="..."> here.
Model values bound by these two components also need to represent your classes, just in a same way as selected items' values. For <h:selectOneMenu> it is value="#{}"; for <h:selectManyListbox> it is value="#{}" with YourClass selectOneMenuValue and List<YourClass> selectManyListboxValues or YourClass[] selectManyListboxValues bean properties respectively.
Population of second select will be handled via <f:ajax> tag. As contents need to be calculated 'on the fly', the right spot to make it is within its listener attribute (i.e. to have List<YourClass> contentsOfSecondListbox = createListboxValues(YourClass oneMenuSelectedOption);) . As you'd desire to rerender the second element, specify its client id in render attribute of <f:ajax>. Example here.
In case you are binding, for example, to String/String[] values, you won't need the converter parts.
Try to go through it step by step to find out your errors and correct them.

EL evaluation in non-rendered JSF elements

Is EL #{myBean.property} evaluated in example below? If yes, that means all ELs on page are evaluated regardless of value of their 'rendered' (or any other) attribute?
<h:panelGroup rendered="false">
<h:outputText value="#{myBean.property}" />
</h:panelGroup>
Is EL #{myBean.property} evaluated in example below?
No. You could also easily answer it yourself by putting a debug breakpoint on the getter method.
If yes, that means all ELs on page are evaluated regardless of value of their 'rendered' (or any other) attribute?
That basically depends on how well designed the component is. The standard JSF components doesn't do that, but if it's for example a custom component which doesn't check isRendered() inside processXxx methods before continuing processing itself and children, then all the EL of the children may be evaluated.

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