Friday, November 25, 2022

Oracle ADF selectManyCheckbox

 The following related to Jdeveloper 12g


Sometimes you may need to create a list with many select options, that can be a selectManyCheckbox or selectManyChoiche, saving the information from this list in a single column on the db.

Luckily for us there is a simple way to halde this need.

First you need to have a db column type varchar2 with size big enough to host the string rappresented by all the ids of the list plus the separator.

Then you have to create the list of values on the View Object attribute.




In the View Object source, in the attribute's properties you should add manually <DISPLAYWIDTH Value="100"/> and modify controltype in <CONTROLTYPE Value="delimited_ids_choice"/>.




Always in the View Object source you have to insert in the listbinding tag the delimiter you'd like to have using the property Delimiter, in my case for using the comma I added Delimiter=",".




Now you have to drag and drop the attribute from the data control to the jsf/jsff as you are creating a selectOneChoice list.




Once the list is created, in the source you can change manually the component tag to selectManyCheckbox or selectManyChoiche as you wish.

I've added a valueChangeListener to study components that are involved java side:


    public void onChangeManyCheck(ValueChangeEvent valueChangeEvent) {
        RichSelectManyCheckbox rsmc = null;
        rsmc = (RichSelectManyCheckbox)valueChangeEvent.getComponent();
        System.out.println("newValue = " + valueChangeEvent.geNewValue());
        String[] keyParams = rsmc.getLabel().split(",");
        for (UIComponent c : rsmc.getChildren()) {
            System.out.println("name = " + c.getClass().getName());
            if (c instanceof UISelectItems ) {
                UISelectItems usi = (UISelectItems) c;
                System.out.println("getChildCount = " + usi.getChildCount());
                System.out.println("getValue = " + usi.getValue() + " class " + usi.getValue().getClass().getName());
                List sia = (List) usi.getValue();
                for (Object sio : sia) {
                    System.out.println("val = " + ((SelectItem) sio).getValue());
                    System.out.println("lab = " + ((SelectItem) sio).getLabel());
                }
            }
         }

The output is:

newValue = [0,1]
name= javax.faces.component.UISelectItems
getChildCount = 0
getValue = [javax.faces.model.SelectItem@f7827d7, javax.faces.model.SelectItem@62627882] class oracle.adfinternal.view.faces.model.binding.FacesCtrlListBinding$1
val = 0
lab = LABEL1
val = 1
lab = LABEL1

the value of the SelectItem in the component is not the value setted on the list of value in the business component, but is the index into the list.

The attributeValue of the binding component into the pageDef does not return a value
instead the inputValue of the binding component into the pageDef contains the index
Is necessary operate on the attributeValue by java.

At this point you have to create a List <Object> in a bean in the task flow where is located the jsf/jsff, and modify the accessors of this list in this way:

  public void setDescrizioneList(List<Object> tfList) {
        JUCtrlListBinding bindList = getAttTrAss("Descrizione");
        if (bindList != null && tfList!=null && !tfList.isEmpty()) {
            bindList.setAttributeValue(tfList.toString().replace("[", "").replace("]", "").replace(" ", ""));
        }
        else {
            bindList.setAttributeValue(null);
        }

        this.tfList = tfList;
    }
       
    public List<Object> getDescrizioneList() {
        JUCtrlListBinding bindList = getAttTrAss("Descrizione");
        tfList = new ArrayList<>();
        if (bindList != null) {
            if(bindList.getAttributeValue()!=null){
                Object[] selectedValues = bindList.getAttributeValue().toString().split(",");
                for(Object item : selectedValues){
                    if(item!=null)
                        //the list contains index of the item
                        tfList.add(Integer.paseInt(item.toString()));
                }
            }
        }
        return tfList;
    }

And you need to add this method to the same bean:
   
    private JUCtrlListBinding getAttTrAss(String name) {
            BindingContext bctx = BindingContext.getCurrent();
            BindingContainer bindings = bctx.getCurrentBindingsEntry();
            JUCtrlListBinding list = (JUCtrlListBinding) bindings.get(name);
            return list;
    }



The last step to make it work is to change the value of the list in the source of the jsf/jsff with the List<Object> of the bean we just created and to set the autosubmit property to true.



No comments:

Post a Comment