This post does not contain anything spectacular. I will discuss various ways in UIX to conditionally display elements using very trivial techniques – a databound rendered attribute, the if element and the switcher element. It is meant primarily for me, myself and I, as I always seem to forget how to use these elements. ADF UIX, previously known as just UIX and earlier sometimes refered to as CABO, has been around in various incarnations for quite some time – perhaps as long as five years. I have worked with UIX at least as far back as 2001. Yet, today when I had to conditionally display certain elements in the ADF application we are currently developing at one of our customer’s projects, I had to reread the documentation (not very helpful) and Google around ( this weblog proved helpful J2EE development with Oracle products, even though it did not contain any straightforward answers for my problems). Another potentially useful blog is Jonas Jacobi’s ADF UIX & JavaServer Faces blog – that has moved to I will record my findings of the day – if they are useful, to you, that would be nice. At least I know where to Google the next time I’m stuck!
Note: one thing the on line help does provide is very quick context sensitive help on UIX elements; in the UIX editor with the cursor on a particular element, just press F1 and the relevant help – not necessarily useful or complete – will be displayed.
Conditionally render a button – use the dynamic render attribute
One of the pages in the application contains a ‘Create New Company’ button that takes the user to a page where a new Company can be created. However, that button is only to be displayed when the application is not already in ‘create mode’ and only when the user has the ‘admin’ privilege. The UserObject has been stored in the (Http)SessionScope, immediately after login. This object has several public methods, including a public boolean isAdmin() method. This method can be referred to using an EL-expression ${sessionScope.jshUser.admin}.
ADF UIX allows us to use EL expressions in the definitions of attributes – where before we had to use the databound syntax of data:rendered="someDataObject.someProperty"
where someDataObject could be any object in the “Rendering Scope” that implements the DataObject interface (with an public Object select(String key)
method that is similar to the get(String key) method on the Map interface that is more commonly used). These EL-expressions can refer to objects in the various scopes (Application, Session, Request and Scope) as well as to Object in the UIX rendering context, for example the bindings that are set up through the ADF bindingframework and its DataControls and PageUIModels (see the post Mastering the ADF UIX contents tag for a very crisp and clear example of UIX and the ADF bindingsframework).
The button I want to conditionally display has an attribute rendered. I can assign a fixed value – true or false – to that attribute, but more interestingly, I can assign it an EL-expression that is dynamically evaluated when the page is rendered:
<button onClick="doEvent('Create');" rendered="${!createMode and sessionScope.jhsUser.admin}" textAndAccessKey="${nls.NEW_BUTTON_LABEL_COMPANIES}" />
The button will only be displayed when the expression ${!createMode and sessionScope.jhsUser.admin} evaluates to true – which is when createMode is false and the IsAdmin method on the UserObject in the SessionScope returns true.
Note: the createMode
that I refer to is actually a Request Scope attribute, set by a Servlet before invoking the UIX page. It is set through
HttpServletRequest request = daContext.getHttpServletRequest(); request.setAttribute(CREATE_MODE,Boolean.valueOf(true));
Conditionally bind an attribute to one or another dynamic value – use the if-element
It may occur – as it does in our application – that you want to dynamically derive the value of an attribute; however, it is also dynamically determined from which element this value will be dynamically retrieved. For example, in our application: if the record is currently being inserted, then the value for a certain item must be derived from the user object in the sessionScope. If however the record is being edited or simply displaye, the value should be derived from the ADF binding.
<formValue name="DptId" id="${bindings.ListsDptId.path}"> <boundAttribute name="value"> <if> <dataObject source="${!createMode}"/> <dataObject source="${bindings.ListsDptId}"/> <dataObject source="${sessionScope.jhsUser.dptId}"/> </if> </boundAttribute> </formValue>
In this example, the value attribute of the <formValue> element is dynamically derived using the EL-expression ${bindings.ListsDptId}
when the expression !createMode evaluates to true. When that expression results in FALSE then the formValue’s value attribute is dynamically derived as ${sessionScope.jhsUser.dptId}
. Note that the <if> element’s children represent the if, then and optional else clause of a if-then-else statement. The Then and Else clauses can also contain fixed text (<fixed text=""/>
).
Conditionally include a UI-node – the switcher element
In the tab-bar for the application, I have several link-elements that are only to be displayed when the current user has a certain role. However, the <link> element in UIX does not have a ‘rendered’ attribute that I can have dynamically derived through some EL-expression. Here I had to make use of the so called <switcher> element, that is like a CASE-WHEN expression that can dynamically include UI Nodes such as a link.
<switcher childName="${sessionScope.jhsUser.authorizations['lobs']}"> <case name="true"> <link text="Business" destination="javascript:doNavigate('StartBusinesses.do');"/> </case> </switcher>
In this example, we test for the result of the EL-expression ${sessionScope.jhsUser.authorizations[‘lobs’]}. This refers to the public Map getAuthorizations()
method on the UserObject that contains key/value pairs for the items on the menu. The key is name of the menu item, such as lobs, the value is either Boolean.TRUE or Boolean.FALSE. When the expression evaluates to true – as will happen when the user has the privilege to access the menu-item – the link-element is included in the page. Otherwise, nothing happens. Note that multiple <case> elements can be included to test for multiple values of the expression in the childname attribute. Note: you can use a <default> element for ‘otherwise’.
Greetings!
I’m currently customizing the presentation in Discoverer Viewer and starting to work with the .uix format.
I have now only one single issue: I would like to show a tree collapsed when my page load.
This is the code responsible for showing it:
This is the code for the event:
The disclosed attribute sets if it is expanded (true) or collapsed (false). By default, the value ${uix.eventResult.paramshs} is true. After reading this artivle, I used the ! operator and set disclosed=”${!uix.eventResult.paramshs}” and it worked (it was collapsed on load)! Unfortunately, nothinng happened on click: the event didn’t work in this condition 🙁
I’d be glad if you could help me!
Best regards,
Ricardo Pinto.
Greetings!
I’m currently customizing the presentation in Discoverer Viewer and starting to work with the .uix format. I have now only one single issue: I would like to show a tree collapsed when my page load.
The code is:
The disclosed attribute sets if it the tree is expanded (true) or collapsed (false). By default, the value ${uix.eventResult.paramshs} is true. After reading this article, I used the logical operator ‘!’ to get the logical not of the value. When I entered my page, it worked: the tree was collapsed! Unfortunately, the event didn’t work anymore (it never expanded) 🙁
This is the event code:
Could you help me on this?
Thanks in advance,
Ricardo Pinto
Hi Lucas,
I’ve got 2 remarks; re the first item; I think you can get a cleaner separation of presentation (the way it looks) and behaviour if you move the rules (ie behaviour) that determine whether the button is displayed or not, out of the page and into a UI-helperbean-property. Let the getter for the property return a boolean indicating visible or not.
The same approach can be applied to the second item; the initialisation of the object that’s edited in the screen should belong in the controller, not in the view layer.
Don’t know how easy this can be realized using UIX and ADF, currently I’m looking at JSF where it’s rather straightforward. As Oracle’s JSF implementation (ADF-Faces) builds upon UIX I would expect it to be feasable…
Cheers, Hans