Deck Transition changes Checkbox’s value (Oracle Jdeveloper 12.1.3.0)

Rigas PapazisisFusion Middleware, Oracle ADF Leave a Comment

A really nice new feature introduced in ADF 12c is the deck ui component. Two helpful examples on how to use this component are the following:

You can find some more examples over the internet but since it’s a new feature I haven’t been able to find too many different implementations and suggestions. These two above are pretty much all you need for simple deck UIs.

Now let’s cut to the chase. The past few days I came across something that I think it’s a bug and it truly bothers me. The use case is pretty simple.

We have a read only table of employees where one of the attributes is a boolean checkbox and in a second deck you edit the selected employee. It seems that something is not working right with the checkbox component.

Add an attribute in the HR schema, in Employees table (say “IsActive” with values “Y” or “N”) and create the Employees entity and the EmployeesView viewObject.

Design the first deck as follows:

employees_table

Now, by clicking “Edit Employee” button we change deck to a second one where the attributes of the employee are editable (in the example we kept some in read only).

editemployees_brokencheckbox

Here is the problem! On click, the valueChangeListener of the checkbox in the second deck is entered and the attribute is set to “N”. So by selecting to edit an employee automatically the IsActive attribute is set to “N”.

The strange thing is that this happens only if in the second deck we are using a checkbox! If you use a selectOneChoice (binding the attribute to an LOV) or just an inputText, you will see that the correct value is displayed. Also everything seems to work fine if, instead of a deck, you are working with popups or navigating to fragments. What it really bothers me is that the use case of having a popup instead of a deck should behave the same, since it’s exactly the same attributes mapped to the same bindings.

The source code of my page is:


<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html>
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
<af:document title="employees.jsf" id="d1">
<af:messages id="m1"/>
<af:form id="f1">
<af:deck id="d3" displayedChild="#{viewScope.box ne 'pb2' ? 'pb1' : 'pb2'}" partialTriggers="pc1:b1 b3">
<af:panelBox text="Employees" id="pb1" showDisclosure="false">
<f:facet name="toolbar"/>
<af:panelGroupLayout layout="vertical" id="pgl1">
<af:query id="qryId1" headerText="Search" disclosed="true"
value="#{bindings.EmployeesViewCriteriaQuery.queryDescriptor}"
model="#{bindings.EmployeesViewCriteriaQuery.queryModel}"
queryListener="#{bindings.EmployeesViewCriteriaQuery.processQuery}"
queryOperationListener="#{bindings.EmployeesViewCriteriaQuery.processQueryOperation}"
resultComponentId="::pc1"/>
<af:panelCollection id="pc1" styleClass="AFStretchWidth" featuresOff="detach">
<f:facet name="menus"/>
<f:facet name="toolbar">
<af:toolbar id="t1">
<af:button id="b1" text="Edit Employee" partialSubmit="false"><af:setPropertyListener from="#{'pb2'}"
to="#{viewScope.box}"
type="action"/></af:button>
</af:toolbar>
</f:facet>
<f:facet name="statusbar"/>
<af:table value="#{bindings.EmployeesView1.collectionModel}" var="row"
rows="#{bindings.EmployeesView1.rangeSize}"
emptyText="#{bindings.EmployeesView1.viewable ? 'No data to display.' : 'Access Denied.'}"
rowBandingInterval="0"
selectedRowKeys="#{bindings.EmployeesView1.collectionModel.selectedRow}"
selectionListener="#{bindings.EmployeesView1.collectionModel.makeCurrent}"
rowSelection="single" fetchSize="#{bindings.EmployeesView1.rangeSize}"
id="resId1" shortDesc="test" summary="test">
<af:column sortProperty="#{bindings.EmployeesView1.hints.LastName.name}" sortable="true"
headerText="#{bindings.EmployeesView1.hints.LastName.label}" id="resId1c1"
width="150" rowHeader="true">
<af:outputText value="#{row.LastName}"
shortDesc="#{bindings.EmployeesView1.hints.LastName.tooltip}"
id="ot1"/>
</af:column>
<af:column sortProperty="#{bindings.EmployeesView1.hints.FirstName.name}"
sortable="true" headerText="#{bindings.EmployeesView1.hints.FirstName.label}"
id="resId1c2" width="150">
<af:outputText value="#{row.FirstName}"
shortDesc="#{bindings.EmployeesView1.hints.FirstName.tooltip}"
id="ot2"/>
</af:column>
<af:column sortProperty="#{bindings.EmployeesView1.hints.Email.name}" sortable="true"
headerText="#{bindings.EmployeesView1.hints.Email.label}" id="resId1c3"
width="150">
<af:outputText value="#{row.Email}"
shortDesc="#{bindings.EmployeesView1.hints.Email.tooltip}" id="ot3"/>
</af:column>
<af:column sortProperty="#{bindings.EmployeesView1.hints.PhoneNumber.name}"
sortable="true"
headerText="#{bindings.EmployeesView1.hints.PhoneNumber.label}"
id="resId1c4">
<af:outputText value="#{row.PhoneNumber}"
shortDesc="#{bindings.EmployeesView1.hints.PhoneNumber.tooltip}"
id="ot4"/>
</af:column>
<af:column sortProperty="#{bindings.EmployeesView1.hints.HireDate.name}" sortable="true"
headerText="#{bindings.EmployeesView1.hints.HireDate.label}" id="resId1c5">
<af:outputText value="#{row.HireDate}"
shortDesc="#{bindings.EmployeesView1.hints.HireDate.tooltip}"
id="ot5">
<af:convertDateTime pattern="#{bindings.EmployeesView1.hints.HireDate.format}"/>
</af:outputText>
</af:column>
<af:column sortProperty="#{bindings.EmployeesView1.hints.Salary.name}" sortable="true"
headerText="#{bindings.EmployeesView1.hints.Salary.label}" id="resId1c6">
<af:outputText value="#{row.Salary}"
shortDesc="#{bindings.EmployeesView1.hints.Salary.tooltip}" id="ot6">
<af:convertNumber groupingUsed="false"
pattern="#{bindings.EmployeesView1.hints.Salary.format}"/>
</af:outputText>
</af:column>
<af:column headerText="#{bindings.EmployeesView1.hints.JobId.label}" id="c1">
<af:outputText value="#{row.JobId}"
shortDesc="#{bindings.EmployeesView1.hints.JobId.tooltip}" id="ot7"/>
</af:column>
<af:column headerText="#{bindings.EmployeesView1.hints.IsActive.label}" id="c2">
<af:selectBooleanCheckbox value="#{row.bindings.IsActive.inputValue}"
label="#{row.bindings.IsActive.label}"
shortDesc="#{bindings.EmployeesView1.hints.IsActive.tooltip}"
id="sbc1" readOnly="true"/>
</af:column>
</af:table>
</af:panelCollection>
</af:panelGroupLayout>
</af:panelBox>
<af:panelBox text="Edit Employee" id="pb2">
<af:panelFormLayout id="pfl1">
<af:panelLabelAndMessage label="#{bindings.LastName.hints.label}" id="plam1">
<af:outputText value="#{bindings.LastName.inputValue}"
shortDesc="#{bindings.LastName.hints.tooltip}" id="ot8"/>
</af:panelLabelAndMessage>
<af:inputText value="#{bindings.FirstName.inputValue}" label="#{bindings.FirstName.hints.label}"
required="#{bindings.FirstName.hints.mandatory}"
columns="#{bindings.FirstName.hints.displayWidth}"
maximumLength="#{bindings.FirstName.hints.precision}"
shortDesc="#{bindings.FirstName.hints.tooltip}" id="it1" autoSubmit="true">
<f:validator binding="#{bindings.FirstName.validator}"/>
</af:inputText>
<af:inputText value="#{bindings.Email.inputValue}" label="#{bindings.Email.hints.label}"
required="#{bindings.Email.hints.mandatory}"
columns="#{bindings.Email.hints.displayWidth}"
maximumLength="#{bindings.Email.hints.precision}"
shortDesc="#{bindings.Email.hints.tooltip}" id="it2" autoSubmit="true">
<f:validator binding="#{bindings.Email.validator}"/>
</af:inputText>
<af:inputText value="#{bindings.PhoneNumber.inputValue}"
label="#{bindings.PhoneNumber.hints.label}"
required="#{bindings.PhoneNumber.hints.mandatory}"
columns="#{bindings.PhoneNumber.hints.displayWidth}"
maximumLength="#{bindings.PhoneNumber.hints.precision}"
shortDesc="#{bindings.PhoneNumber.hints.tooltip}" id="it3" autoSubmit="true">
<f:validator binding="#{bindings.PhoneNumber.validator}"/>
</af:inputText>
<af:panelLabelAndMessage label="#{bindings.HireDate.hints.label}" id="plam2">
<af:outputText value="#{bindings.HireDate.inputValue}"
shortDesc="#{bindings.HireDate.hints.tooltip}" id="ot9">
<af:convertDateTime pattern="#{bindings.HireDate.format}"/>
</af:outputText>
</af:panelLabelAndMessage>
<af:panelLabelAndMessage label="#{bindings.Salary.hints.label}" id="plam3">
<af:outputText value="#{bindings.Salary.inputValue}"
shortDesc="#{bindings.Salary.hints.tooltip}" id="ot10">
<af:convertNumber groupingUsed="false" pattern="#{bindings.Salary.format}"/>
</af:outputText>
</af:panelLabelAndMessage>
<af:selectBooleanCheckbox value="#{bindings.IsActive.inputValue}"
label="#{bindings.IsActive.label}"
shortDesc="#{bindings.IsActive.hints.tooltip}" id="sbc2"
autoSubmit="true"/>
</af:panelFormLayout>
<af:button actionListener="#{bindings.Commit.execute}" text="Save"
disabled="#{!bindings.Commit.enabled}" id="b2"/>
<af:button text="Back" id="b3" ><af:setPropertyListener from="#{'pb1'}"
to="#{viewScope.box}"
type="action"/></af:button>
</af:panelBox>
<af:transition triggerType="forwardNavigate" transition="flipRight"/>
<af:transition triggerType="backNavigate" transition="flipLeft"/>
</af:deck>
</af:form>
</af:document>
</f:view>

and the PageDef:


<?xml version="1.0" encoding="UTF-8" ?>
<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="12.1.3.13.26" id="employeesPageDef"
Package="pages">
<parameters/>
<executables>
<variableIterator id="variables"/>
<iterator Binds="EmployeesView1" RangeSize="25" DataControl="AppModuleDataControl" id="EmployeesView1Iterator"/>
<searchRegion Criteria="EmployeesViewCriteria" Customizer="oracle.jbo.uicli.binding.JUSearchBindingCustomizer"
Binds="EmployeesView1Iterator" id="EmployeesViewCriteriaQuery"/>
</executables>
<bindings>
<tree IterBinding="EmployeesView1Iterator" id="EmployeesView1">
<nodeDefinition DefName="com.nodalpoint.hrtest.model.views.EmployeesView" Name="EmployeesView10">
<AttrNames>
<Item Value="LastName"/>
<Item Value="FirstName"/>
<Item Value="Email"/>
<Item Value="PhoneNumber"/>
<Item Value="HireDate"/>
<Item Value="Salary"/>
<Item Value="JobId"/>
<Item Value="IsActive" Binds="IsActive"/>
</AttrNames>
</nodeDefinition>
</tree>
<action id="Commit" RequiresUpdateModel="true" Action="commitTransaction" DataControl="AppModuleDataControl"/>
<button IterBinding="EmployeesView1Iterator" id="IsActive" DTSupportsMRU="false" StaticList="true">
<AttrNames>
<Item Value="IsActive"/>
</AttrNames>
<ValueList>
<Item Value="Y"/>
<Item Value="N"/>
</ValueList>
</button>
<attributeValues IterBinding="EmployeesView1Iterator" id="LastName">
<AttrNames>
<Item Value="LastName"/>
</AttrNames>
</attributeValues>
<attributeValues IterBinding="EmployeesView1Iterator" id="FirstName">
<AttrNames>
<Item Value="FirstName"/>
</AttrNames>
</attributeValues>
<attributeValues IterBinding="EmployeesView1Iterator" id="Email">
<AttrNames>
<Item Value="Email"/>
</AttrNames>
</attributeValues>
<attributeValues IterBinding="EmployeesView1Iterator" id="PhoneNumber">
<AttrNames>
<Item Value="PhoneNumber"/>
</AttrNames>
</attributeValues>
<attributeValues IterBinding="EmployeesView1Iterator" id="HireDate">
<AttrNames>
<Item Value="HireDate"/>
</AttrNames>
</attributeValues>
<attributeValues IterBinding="EmployeesView1Iterator" id="Salary">
<AttrNames>
<Item Value="Salary"/>
</AttrNames>
</attributeValues>
</bindings>
</pageDefinition>

SR is also filed (SR no 3-11011746371).

I haven’t found any workaround yet so I just use a selectOneChoice to edit. Well… we have to adapt in order to provide.

 

Edit:

It is confirmed as a bug. Check My Oracle Support for Bug 21457198 – DECK TRANSITION CHANGES/RESETS SELECTBOOLEANCHECKBOX’S VALUE

Rigas Papazisis
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments