Prerequisites of this implementation :
This class will open the LOV window in a popup and also when user selects a row and click OK in the popup, it will set the value property of the input Text ui component where this LOV is invoked from.
// Add the getters and setters of all the class level attributes.
// I have removed them from this example to shorten the length of the blog.
// For "getUIComponent()" check my other blog to find a UI Component from managed bean
public class MyLOVListener {
/**
* ID of the popup where af:table is defined
*/
private String popupId;
/**
* ID of the inputText component where the selected value
* from the popup should be copied back
*/
private String inputTextId;
/**
* Name of the iterator defined the in pagedef, from which the selected row
* can be read
*/
private String iteratorName;
/**
* Name of the attribute of the view object which should be read and copied
* back to the "inputText" component
*/
private String attributeName;
/**
* Name of the view object
*/
private String viewObjectToQuery;
public void openLOV(ActionEvent actionEvent) {
ViewObjectImpl lovViewObject = (ViewObjectImpl) Constants.getService().findViewObject(getViewObjectToQuery());
lovViewObject.executeQuery();
RichPopup.PopupHints ph = new RichPopup.PopupHints();
((RichPopup)getUIComponent(getPopupId())).show(ph);
}
public void setSelectedRow(DialogEvent dialogEvent) {
if(dialogEvent.getOutcome() == DialogEvent.Outcome.ok) {
DCBindingContainer bindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding dcItteratorBindings = bindings.findIteratorBinding(getIteratorName());
ViewObject voTableData = dcItteratorBindings.getViewObject();
// Get selected row
Row rowSelected = voTableData.getCurrentRow();
if (rowSelected != null) {
RichInputText inputTextBox = (RichInputText)getUIComponent(getInputTextId());
inputTextBox.resetValue();
inputTextBox.setValue((String)rowSelected.getAttribute(getAttributeName()));
AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
adfFacesContext.addPartialTarget(inputTextBox);
}
}
}
}
Declare this class as a taskFlow managed bean
<managed-bean id="__7">
<managed-bean-name id="__8">MyLOVListener</managed-bean-name>
<managed-bean-class id="__6">com.view.beans.MyLOVListener</managed-bean-class>
<managed-bean-scope id="__5">pageFlow</managed-bean-scope>
</managed-bean>
#2. Managed bean for auto suggest behaviour :
public class MyAutoSuggestionListener {
public List getEmployees(String employee) {
List<SelectItem> matchingItemsList = new ArrayList<SelectItem>();
if(employee != null) {
matchingItemsList = getMatchingItems(getService().getMyViewObject(), "employee", employee);
}
return matchingItemsList;
}
private ApplicationModuleImpl getService() {
return ((ApplicationModuleImpl)AppModuleBean.getService(FacesContext.getCurrentInstance(), "MyAppModule"));
}
private List getMatchingItems(ViewObjectImpl viewObject, String attributeName, String stringToMatch) {
List<SelectItem> matchingItemsList = new ArrayList<SelectItem>();
viewObject.executeQuery();
for (Row row : viewObject.getAllRowsInRange()) {
String matchingEntries = (String)row.getAttribute(attributeName);
if(matchingEntries.toUpperCase().startsWith(stringToMatch.toUpperCase())) {
matchingItemsList.add(new SelectItem(matchingEntries, matchingEntries));
}
}
return matchingItemsList;
}
}
Declare this class as a taskFlow managed bean
<managed-bean id="__9">
<managed-bean-name id="__16">MyAutoSuggestionListener</managed-bean-name>
<managed-bean-class id="__15">view.beans.MyAutoSuggestionListener</managed-bean-class>
<managed-bean-scope id="__14">pageFlow</managed-bean-scope>
</managed-bean>
#3. Add input Text for the LOV :
<af:inputText simple="true" id="employeeIt1" columns="25">
<af:autoSuggestBehavior maxSuggestedItems="40"
suggestedItems="#{pageFlowScope.MyAutoSuggestionListener.getEmployees}"/>
</af:inputText>
<af:spacer id="sp1" width="3"/>
<af:commandImageLink id="empPopup" icon="/common/images/details.png"
immediate="true" partialSubmit="true"
actionListener="#{pageFlowScope.MyLOVListener.openLOV}">
<af:setPropertyListener from="employeeIt1" to="#{pageFlowScope.MyLOVListener.inputTextId}" type="action"/>
<af:setPropertyListener from="employeePopup" to="#{pageFlowScope.MyLOVListener.popupId}" type="action"/>
<af:setPropertyListener from="MyViewObjectIterator" to="#{pageFlowScope.MyLOVListener.iteratorName}" type="action"/>
<af:setPropertyListener from="employee" to="#{pageFlowScope.MyLOVListener.attributeName}" type="action"/>
<af:setPropertyListener from="MyViewObject" to="#{pageFlowScope.MyLOVListener.viewObjectToQuery}" type="action"/>
</af:commandImageLink>
In the above command image link : the icon used is a spy glass, which normally used by ADF in case of LOV in a popup.
#4. Add the popup for LOV in the page:
First define a af:popup element in the page like below :
<af:popup autoCancel="disabled" childCreation="immediate" id="employeePopup">
<af:dialog id="employeeDialog" dialogListener="#{pageFlowScope.MyLOVListener.setSelectedRow}">
</af:dialog></af:popup>
Then drag and drop the view object from DataControls panel in JDeveloper. Make sure you display it as a read only table. It will look like below :
<af:popup autoCancel="disabled" childCreation="immediate" id="employeePopup">
<af:dialog id="employeeDialog"
dialogListener="#{pageFlowScope.MyLOVListener.setSelectedRow}">
<af:table value="#{bindings.MyViewObject.collectionModel}"
var="row"
rows="#{bindings.MyViewObject.rangeSize}"
emptyText="#{bindings.MyViewObject.viewable ? 'No data to display.' : 'Access Denied.'}"
fetchSize="#{bindings.MyViewObject.rangeSize}"
rowBandingInterval="0"
selectedRowKeys="#{bindings.MyViewObject.collectionModel.selectedRow}"
selectionListener="#{bindings.MyViewObject.collectionModel.makeCurrent}"
rowSelection="single" id="t1">
<af:column sortProperty="#{bindings.MyViewObject.hints.employee.name}"
sortable="true"
headerText="#{bindings.MyViewObject.hints.employee.label}"
id="c2" width="400">
<af:outputText value="#{row.employee}" id="ot1"/>
</af:column>
</af:table>
</af:dialog>
</af:popup>
This implementation has some advantages :
- ViewObject (in the example it is "MyViewObject")
- Some utility is used in the example, check my other blogs "ADF Utility"
This class will open the LOV window in a popup and also when user selects a row and click OK in the popup, it will set the value property of the input Text ui component where this LOV is invoked from.
// Add the getters and setters of all the class level attributes.
// I have removed them from this example to shorten the length of the blog.
// For "getUIComponent()" check my other blog to find a UI Component from managed bean
public class MyLOVListener {
/**
* ID of the popup where af:table is defined
*/
private String popupId;
/**
* ID of the inputText component where the selected value
* from the popup should be copied back
*/
private String inputTextId;
/**
* Name of the iterator defined the in pagedef, from which the selected row
* can be read
*/
private String iteratorName;
/**
* Name of the attribute of the view object which should be read and copied
* back to the "inputText" component
*/
private String attributeName;
/**
* Name of the view object
*/
private String viewObjectToQuery;
public void openLOV(ActionEvent actionEvent) {
ViewObjectImpl lovViewObject = (ViewObjectImpl) Constants.getService().findViewObject(getViewObjectToQuery());
lovViewObject.executeQuery();
RichPopup.PopupHints ph = new RichPopup.PopupHints();
((RichPopup)getUIComponent(getPopupId())).show(ph);
}
public void setSelectedRow(DialogEvent dialogEvent) {
if(dialogEvent.getOutcome() == DialogEvent.Outcome.ok) {
DCBindingContainer bindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding dcItteratorBindings = bindings.findIteratorBinding(getIteratorName());
ViewObject voTableData = dcItteratorBindings.getViewObject();
// Get selected row
Row rowSelected = voTableData.getCurrentRow();
if (rowSelected != null) {
RichInputText inputTextBox = (RichInputText)getUIComponent(getInputTextId());
inputTextBox.resetValue();
inputTextBox.setValue((String)rowSelected.getAttribute(getAttributeName()));
AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
adfFacesContext.addPartialTarget(inputTextBox);
}
}
}
}
Declare this class as a taskFlow managed bean
<managed-bean id="__7">
<managed-bean-name id="__8">MyLOVListener</managed-bean-name>
<managed-bean-class id="__6">com.view.beans.MyLOVListener</managed-bean-class>
<managed-bean-scope id="__5">pageFlow</managed-bean-scope>
</managed-bean>
#2. Managed bean for auto suggest behaviour :
public class MyAutoSuggestionListener {
public List getEmployees(String employee) {
List<SelectItem> matchingItemsList = new ArrayList<SelectItem>();
if(employee != null) {
matchingItemsList = getMatchingItems(getService().getMyViewObject(), "employee", employee);
}
return matchingItemsList;
}
private ApplicationModuleImpl getService() {
return ((ApplicationModuleImpl)AppModuleBean.getService(FacesContext.getCurrentInstance(), "MyAppModule"));
}
private List getMatchingItems(ViewObjectImpl viewObject, String attributeName, String stringToMatch) {
List<SelectItem> matchingItemsList = new ArrayList<SelectItem>();
viewObject.executeQuery();
for (Row row : viewObject.getAllRowsInRange()) {
String matchingEntries = (String)row.getAttribute(attributeName);
if(matchingEntries.toUpperCase().startsWith(stringToMatch.toUpperCase())) {
matchingItemsList.add(new SelectItem(matchingEntries, matchingEntries));
}
}
return matchingItemsList;
}
}
Declare this class as a taskFlow managed bean
<managed-bean id="__9">
<managed-bean-name id="__16">MyAutoSuggestionListener</managed-bean-name>
<managed-bean-class id="__15">view.beans.MyAutoSuggestionListener</managed-bean-class>
<managed-bean-scope id="__14">pageFlow</managed-bean-scope>
</managed-bean>
#3. Add input Text for the LOV :
<af:inputText simple="true" id="employeeIt1" columns="25">
<af:autoSuggestBehavior maxSuggestedItems="40"
suggestedItems="#{pageFlowScope.MyAutoSuggestionListener.getEmployees}"/>
</af:inputText>
<af:spacer id="sp1" width="3"/>
<af:commandImageLink id="empPopup" icon="/common/images/details.png"
immediate="true" partialSubmit="true"
actionListener="#{pageFlowScope.MyLOVListener.openLOV}">
<af:setPropertyListener from="employeeIt1" to="#{pageFlowScope.MyLOVListener.inputTextId}" type="action"/>
<af:setPropertyListener from="employeePopup" to="#{pageFlowScope.MyLOVListener.popupId}" type="action"/>
<af:setPropertyListener from="MyViewObjectIterator" to="#{pageFlowScope.MyLOVListener.iteratorName}" type="action"/>
<af:setPropertyListener from="employee" to="#{pageFlowScope.MyLOVListener.attributeName}" type="action"/>
<af:setPropertyListener from="MyViewObject" to="#{pageFlowScope.MyLOVListener.viewObjectToQuery}" type="action"/>
</af:commandImageLink>
In the above command image link : the icon used is a spy glass, which normally used by ADF in case of LOV in a popup.
#4. Add the popup for LOV in the page:
First define a af:popup element in the page like below :
<af:popup autoCancel="disabled" childCreation="immediate" id="employeePopup">
<af:dialog id="employeeDialog" dialogListener="#{pageFlowScope.MyLOVListener.setSelectedRow}">
</af:dialog></af:popup>
Then drag and drop the view object from DataControls panel in JDeveloper. Make sure you display it as a read only table. It will look like below :
<af:popup autoCancel="disabled" childCreation="immediate" id="employeePopup">
<af:dialog id="employeeDialog"
dialogListener="#{pageFlowScope.MyLOVListener.setSelectedRow}">
<af:table value="#{bindings.MyViewObject.collectionModel}"
var="row"
rows="#{bindings.MyViewObject.rangeSize}"
emptyText="#{bindings.MyViewObject.viewable ? 'No data to display.' : 'Access Denied.'}"
fetchSize="#{bindings.MyViewObject.rangeSize}"
rowBandingInterval="0"
selectedRowKeys="#{bindings.MyViewObject.collectionModel.selectedRow}"
selectionListener="#{bindings.MyViewObject.collectionModel.makeCurrent}"
rowSelection="single" id="t1">
<af:column sortProperty="#{bindings.MyViewObject.hints.employee.name}"
sortable="true"
headerText="#{bindings.MyViewObject.hints.employee.label}"
id="c2" width="400">
<af:outputText value="#{row.employee}" id="ot1"/>
</af:column>
</af:table>
</af:dialog>
</af:popup>
This implementation has some advantages :
- If you implement ADF managed LOVs, if the view object returns 0 rows, it throws NullPointer Exception. But this implementation will open an empty table in the popup.
- This implementation is reusable in the same taskFlow for multiple other LOV implementations. You only need to add one extra method in MyAutoSuggestionListener and follow #3 and #4 step for the new LOVs. The LOV listener class is robust enough to handle any new calls.
Comments
Post a Comment