Monday, November 28, 2011

ADF: Auto Suggest - solutions

I had implemented autosuggest on an input text field and it was all working so I moved it into our template to make it available application wide. The component stopped working (bind problem first then it would not return the value I needed into the text box). Here are the fixes.

The component is quick go button functionality with a suggest lookup to any menu link.

Bind problems solution: I needed to lookup the template binding using the current bind did not have my VO:
 BindingContext bctx = BindingContext.getCurrent();
  DCBindingContainer bindings = 
      bctx.findBindingContainer(
      "package_formTemplatePageDef");


Not returning the value solution: I had a uppercase conveter on my input text field - this was messing with my return value on the autosuggest. I removed it and it worked like magic.

The working code (note the query is limited to 5 rows in the VO with a bind variable linked to rownum):

JSFF
<af:panelGroupLayout id="pt_ag12" layout="horizontal">
  <af:inputText labelStyle="color: white" label="Go Link" id="pt_it7" value="#{menuBean.goValue}">
    <af:autoSuggestBehavior suggestItems="#{menuBean.suggestGoItems}"
      maxSuggestedItems="#{menuBean.maxSuggestionResults}"/>
  </af:inputText>
  <af:commandButton text="go" id="pt_cbGo" disabled="#{menuBean.goEnabled}"
    action="#{menuBean.performGo}"/>
</af:panelGroupLayout>

Bean
public int getMaxSuggestionResults() {
  return 5;
}

public List suggestGoItems(
  FacesContext fctx, oracle.adf.view.rich.model.AutoSuggestUIHints hints) {
  ArrayList selectItems = new ArrayList();
  String submittedValue = hints.getSubmittedValue();
  if(submittedValue != null && submittedValue.length() > 3) {
    BindingContext bctx = BindingContext.getCurrent();
    DCBindingContainer bindings = 
      bctx.findBindingContainer(
      "package_formTemplatePageDef");
    DCIteratorBinding binding = bindings.findIteratorBinding("AutoSuggestMenuVOIterator");

    HashMap variables = new HashMap();
    variables.put("userCode", super.getUserCode());
    variables.put("maxLimit", new Integer(getMaxSuggestionResults()));
    variables.put("searchName", submittedValue.toUpperCase());
    ADFUtils.setBindVariables(binding.getViewObject(), variables);
    binding.executeQuery();
    Row[] rows = binding.getAllRowsInRange();
    for(Row row : rows) {
      Object action = row.getAttribute("Action");
      String name = (String) row.getAttribute("Name");
      selectItems.add(new SelectItem(action, name));
    }
  }
  return selectItems;
}

public boolean isGoEnabled() {
  return goValue != null && goValue.length() > 3;
}

public String getGoValue() {
 return goValue;
}

public void setGoValue(String goValue) {
  this.goValue = goValue;
 }

public String performGo() {
  ExternalContext eCtx = JSFUtils.getExternalContext();
  //sql query to get the destination
  String destination = MenuUtility.getDestinationBasedOnKey(goValue, "name");

  if(destination != null) {
    String contextPath = ((HttpServletRequest) eCtx.getRequest()).getContextPath();
    try {
      logger.debug("redirectUrl=[" + contextPath + destination + "]");
      eCtx.redirect(contextPath + destination);
    } catch(Exception e) {
      logger.error("", e);
    }
  }
  return null;
}

ADFUtils.setBindVariables


public static void setBindVariables(ViewObject view, Map variables) {
  VariableValueManager vm = view.ensureVariableManager();
  for(String key : variables.keySet()) {
    vm.setVariableValue(key, variables.get(key));
  }
}

So anyway here are a couple of auto suggestions for the autosuggest component:

1) I want to control the value selected so a on select method would be nice.
2) The no results found text should be easily customized.

No comments:

Post a Comment