X

How to create cascading (depending) auto suggest behavior using BC4J

Arunkumar Ramamoorthy
Consulting Technical Manager

In continuation to my previous blog on "How to create multi
level cascading (dependent) list of values using BC4J
", i am trying
to leverage a similar usecase using af:autoSuggestBehavior in
this article. Though the usecase looks same, the implementation is
slightly different for this.

Let us assume a usecase where we have some text fields with auto
suggest feature enabled, and their suggested items could be
dependent on one other. For ex : Country, State and City.

This could be modeled by having an EO and VO created based on
Person table and read-only look-up VOs created based on Country,
State and City tables.

model.jpg

VOs.jpg

Implementing the dependency between LOVs is pretty straight
forward. However, implementing the dependency between the auto
suggest items is not. In order to achieve the dependency, first we
would need couple of methods returning current row's CountryId and
StateId. We could add them up in the AMImpl class.

public Number
getCurrentCountryId(){

return (Number)
this.getPersonView1().getCurrentRow().getAttribute("CountryId");

}


public Number getCurrentStateId(){

return (Number)
this.getPersonView1().getCurrentRow().getAttribute("StateId");

}

As we need to filter out the States based on the Country and the
City based on the Country & State, we would need to modify the
query of these two VOs to include a bind variable in the where
clause.

whereClause.jpg

For having the auto suggest, we need to have a view criteria
defined for all the three look-up VOs (CountryView, StateView and
CityView).

CountryVC.jpg

StateVC.jpg

CityVC.jpg

Generate VOImpl classes for Country, State and City VOs (with
Include bind variable accessors option checked), and then expose
setBindCountryName (in Country VO), setBindStateName (in State VO)
and setBindCityName (in City VO) methods as client interfaces.

And the last part on the model is to pass the current row's
CountryId and StateId to the Bind Variables defined in the State
and City VOs. Also, we need to get the VCs created above to be
executed by default (By editing the VO instance in the AM's data
model), so that the auto suggest list would be filtered as and when
the users type.

CountryViewAM.jpg

StateViewAM.jpg

CityViewAM.jpg

Here, we specify groovy expression for the CountryId and StateId
as adf.object.applicationModule.<methodName>. For more
information about using groovy expressions, check out this :
http://www.oracle.com/technetwork/developer-tools/jdev/introduction-to-groovy-128837.pdf
.

With this, we are done with setting up the model layer for the
auto suggest dependency.

In the View layer, we would create an ADF Form based on the
Person VO, with all the navigation buttons.

PersonJSPX.jpg

In order to construct the onSuggest items, we would create Tree
Bindings for Country VO, State VO and City VO, along with method
action bindings for the setBindCountryName, setBindStateName and
setBindCityName methods.

pagedef.jpg

Now, we could add af:autoSuggestBehavior for CountryId, StateId
and CityId fields. Then, add onSuggest methods in backing bean for
populating the on suggest items for each fields.

onSuggest method for Country field :

public List onCountrySuggest(String
searchCountryName) {

ArrayList<SelectItem> selectItems = new
ArrayList<SelectItem>();


System.out.println(searchCountryName);

//get access to the
binding context and binding container at runtime

BindingContext bctx =
BindingContext.getCurrent();

BindingContainer
bindings = bctx.getCurrentBindingsEntry();

//set the bind variable
value that is used to filter the View Object

//query of the suggest
list. The View Object instance has a View

//Criteria
assigned

OperationBinding
setVariable = (OperationBinding)
bindings.get("setBind_CountryName");

setVariable.getParamsMap().put("value", searchCountryName);

setVariable.execute();

//the data in the
suggest list is queried by a tree binding.

JUCtrlHierBinding
hierBinding = (JUCtrlHierBinding)
bindings.get("CountryView1");



//re-query the list
based on the new bind variable values

hierBinding.executeQuery();


//The rangeSet, the
list of queries entries, is of type

//JUCtrlValueBndingRef.

List<JUCtrlValueBindingRef> displayDataList =
hierBinding.getRangeSet();


for
(JUCtrlValueBindingRef displayData : displayDataList){

Row rw = displayData.getRow();

//populate the SelectItem list

selectItems.add(new SelectItem(

(Integer)rw.getAttribute("Id"),

(String)rw.getAttribute("Name")));

}


return
selectItems;

}

onSuggest method for State field :


public List onStateSuggest(String
searchStateName) {

ArrayList<SelectItem> selectItems = new
ArrayList<SelectItem>();


System.out.println(searchStateName);

//get access to the
binding context and binding container at runtime

BindingContext bctx =
BindingContext.getCurrent();

BindingContainer
bindings = bctx.getCurrentBindingsEntry();

//set the bind variable
value that is used to filter the View Object

//query of the suggest
list. The View Object instance has a View

//Criteria
assigned

OperationBinding
setVariable = (OperationBinding)
bindings.get("setBind_StateName");

setVariable.getParamsMap().put("value", searchStateName);

setVariable.execute();

//the data in the
suggest list is queried by a tree binding.

JUCtrlHierBinding
hierBinding = (JUCtrlHierBinding) bindings.get("StateView1");



//re-query the list
based on the new bind variable values

hierBinding.executeQuery();


//The rangeSet, the
list of queries entries, is of type

//JUCtrlValueBndingRef.

List<JUCtrlValueBindingRef> displayDataList =
hierBinding.getRangeSet();


for
(JUCtrlValueBindingRef displayData : displayDataList){

Row rw = displayData.getRow();

//populate the SelectItem list

selectItems.add(new SelectItem(

(Integer)rw.getAttribute("Id"),

(String)rw.getAttribute("Name")));

}


return
selectItems;

}

onSuggest method for City field :

public List onCitySuggest(String
searchCityName) {

ArrayList<SelectItem> selectItems = new
ArrayList<SelectItem>();


System.out.println(searchCityName);

//get access to the
binding context and binding container at runtime

BindingContext bctx =
BindingContext.getCurrent();

BindingContainer
bindings = bctx.getCurrentBindingsEntry();

//set the bind variable
value that is used to filter the View Object

//query of the suggest
list. The View Object instance has a View

//Criteria
assigned

OperationBinding
setVariable = (OperationBinding)
bindings.get("setBind_CityName");

setVariable.getParamsMap().put("value", searchCityName);

setVariable.execute();

//the data in the
suggest list is queried by a tree binding.

JUCtrlHierBinding
hierBinding = (JUCtrlHierBinding) bindings.get("CityView1");



//re-query the list
based on the new bind variable values

hierBinding.executeQuery();


//The rangeSet, the
list of queries entries, is of type

//JUCtrlValueBndingRef.

List<JUCtrlValueBindingRef> displayDataList =
hierBinding.getRangeSet();


for
(JUCtrlValueBindingRef displayData : displayDataList){

Row rw = displayData.getRow();

//populate the SelectItem list

selectItems.add(new SelectItem(

(Integer)rw.getAttribute("Id"),

(String)rw.getAttribute("Name")));

}


return
selectItems;

}

Once after this, we could bind this to the
af:autoSuggestBehavior's suggestedItems property


<af:inputText value="#{bindings.CountryId.inputValue}"
label="#{bindings.CountryId.hints.label}"

columns="#{bindings.CountryId.hints.displayWidth}"

autoSubmit="true"

shortDesc="#{bindings.CountryId.hints.tooltip}" id="it3">

<af:autoSuggestBehavior
suggestedItems="#{viewScope.AutoSuggestBean.onCountrySuggest}"/>

</af:inputText>

<af:inputText value="#{bindings.StateId.inputValue}"
label="#{bindings.StateId.hints.label}"

columns="#{bindings.StateId.hints.displayWidth}"

autoSubmit="true" partialTriggers="it3"

shortDesc="#{bindings.StateId.hints.tooltip}" id="it4">

<af:autoSuggestBehavior
suggestedItems="#{viewScope.AutoSuggestBean.onStateSuggest}"/>

</af:inputText>

<af:inputText value="#{bindings.CityId.inputValue}"
label="#{bindings.CityId.hints.label}"

columns="#{bindings.CityId.hints.displayWidth}"

autoSubmit="true" partialTriggers="it4"

shortDesc="#{bindings.CityId.hints.tooltip}" id="it5">

<af:autoSuggestBehavior
suggestedItems="#{viewScope.AutoSuggestBean.onCitySuggest}"/>

</af:inputText>

Finally, our output would be

output1.jpg

output2.jpg

output3.jpg

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.