Showing posts with label dynamically. Show all posts
Showing posts with label dynamically. Show all posts

Monday, 25 November 2013

ADF - In a Button: invoke an Action (control-flow-case) from its ActionListener Programmatically

In the Property Inspector of UIComponents like af:commandButton, af:commandToobarButton, ecc.. there are two important property in the Button Action section: Action and ActionListener.
In Action we can reference a static outcome, for example a control-flow-case for navigate between two fragmgents in the same taskflow.
ActionListener is used to reference a method in a Bean.
If both the two properties are setted the execution will be at the same time, so we can't prevent the execution of the Action.
If we want use the ActionListener for a control so that if and only if this control is positive navigate to another fragment here the solution.
Description of the example:
We have a taskflow with two fragments: Fragment_A and Fragment_B.
Pressing a button (a RichCommandButton) in the Fragment_A we can navigate to Fragment_B only if a control returns "true".
Differently we can navigate from Fragment_B to Fragment_A without any control pressing another button.
To do this we set in the taskfow diagram the "goFragA" control-flow-case to navigate from Fragment_A to Fragment_B and the "goFragB" control-flow-case for back to the Fragment_A.


In the RichCommandButton in the Fragment_B set the action with "goFragA":



In the RichCommandButton in the Fragment_A set the ActionListener with the method:

  public void goToFragmentB(ActionEvent actionEvent) {
    if(<control>){
      RichCommandButton b = (RichCommandButton)actionEvent.getComponent();
      MethodExpression me = JSFUtils.getMethodExpression("goFragB",new Class[]{ActionEvent.class});
      b.setActionExpression(me);
    }else{
      FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR,"Control Failure",null);
      FacesContext.getCurrentInstance().addMessage(null,msg);
    }
  }

This solution is very convent for control the navigation.




Monday, 4 November 2013

ADF - Attribute Binding dynamically created with validations

I needed to dynamically implement an attribute binding on PageDef of my fragment.
After that I could dynamically create also the item (a RichInputText) on the fragment with its validator.
There are 2 cases:
Case A) the items are created in a Table,
Case B) the items are created in a PanelFormLayout.

As has been created in the table (CASE A):


DCBindingContainer dcBindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
JUCtrlHierBinding treeData = (JUCtrlHierBinding)dcBindings.getControlBinding(MyView);
JUCtrlHierNodeBinding nodeBind = treeData.getRootNodeBinding();
/* EDIT - Causes errors in column sorting
* Correction below
* String[] names = nodeBind.getAttributeNames();
int nItem = names.length;
String[] newNames = new String[nItem + 1];
System.arraycopy(names, 0, newNames, 0, nItem);
newNames[nItem] = "MyNewField";
nodeBind.setAttributeNames(newNames);
*/
//EDIT - Correction:
ViewObjectImpl vo = (ViewObjectImpl )treeData.getViewObject();
AttributeDef[] adfs = nodeBind.getAttributeDefs();
int nItem = adfs.length;
AttributeDef[] newAdfs = new AttributeDef[nItem + 1];
System.arraycopy(adfs, 0, newAdfs, 0, nItem);
int newAttrIndex = vo.getAttributeIndexOf(""MyNewField");
newAdfs[nItem] = vo.getAttributeDef(newAttrIndex);
nodeBind.setAttributes(newAdfs);
treeData.setAttributes(newAdfs);

Then I create the RichInputText in a RichColumn in a RichTable with its validator:

ValidatorTag.BindingValidator vb = new ValidatorTag.BindingValidator(null,JSFUtils.getValueExpression("#{row.bindings.MyNewField.validator}"));
((UIXEditableValue)
newRichInputText).addValidator(vb);

It's works!

As has been created in form (CASE B):


DCBindingContainer dcBindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding it = ADFUtils.findIterator("MyViewIterator");
JUCtrlAttrsBinding nb = JUCtrlAttrsBinding.createAttributeBinding((JUFormBinding)dcBindings,null, "MyView", null, "MyViewIterator", "MyNewField");
dcBindings.addControlBinding("MyNewField", nb);


Then I create the RichInputText in a PanelFormLayout with its validator:

ValidatorTag.BindingValidator vb = new ValidatorTag.BindingValidator(null,JSFUtils.getValueExpression("#{bindings.MyNewField.validator}"));
((UIXEditableValue)newRichInputText).addValidator(vb);



It's  don't works!


The problem is on the validator.
I see the new InputText in my page and the value is right, but when I submit the field I see this error:

"Unable to resolve a Validator instance using either validatorId '' or binding '#{bindings.MyNewField.validator}'."


My team has published the question on Oracle Forum without any replies:

https://forums.oracle.com/thread/2513671

How I solved it?


I have dealt the case B as the case A, creating the attribute binding in the same way.

The difference was in creating the item on the page.

Is no longer been inserted in panelFormLayout but inside an Iterator in this way:

UIXIterator iter = new UIXIterator();

iter.setVar("row");
iter.setRows(1);
iter.setValueExpression("value",JSFUtils.getValueExpression("#{bindings.MyView.collectionModel}"));
iter.setValueExpression("first",JSFUtils.getValueExpression("#{bindings.MyView.currentRowIndex}"));
myPanelForm.getChildren().add(iter);

Yes, this is a workaround but now.. It's works.