Overriding Control Hints of a View Object on the fly

I recently came across a use case where the requirement was to fetch Attribute Hints(display width, label etc.) for a View Object(and Entity Object) on the fly from an external system. Let me share a simple possible solution for this specific use case.

A glance at the implementation

The idea is to override ViewRowImpl::createViewRowAttrHints(AttributeDefImpl attrDef) to return a custom implementation of ViewRowAttrHintsImpl class. The same concept has been discussed in one of my previous post sometime back - Decorate UI with view row Attribute's User Interface hints. Please note that, this is the place( custom ViewRowAttrHintsImpl class - LazyViewRowAttrHintsImpl) where we are adding the hook to retrieve the Attribute Hints from third party service.

@Override
protected ViewRowAttrHintsImpl createViewRowAttrHints(AttributeDefImpl attrDef) {
  return new LazyViewRowAttrHintsImpl(attrDef, this);
}

The constructor of LazyViewRowAttrHintsImpl may look like as shown in the following code snippet. Please take a look at th source of LazyViewRowAttrHintsImpl.java to get a feel of the implementation (work space is attached at the end of this post).


 public class LazyViewRowAttrHintsImpl 
                     extends ViewRowAttrHintsImpl {
  
  public LazyViewRowAttrHintsImpl(
           AttributeDefImpl attributeDefImpl,
           ViewRowImpl viewRowImpl) {
    super(attributeDefImpl, viewRowImpl);

    //The following call retrieves AttrHints 
    //from third party service
    //and add the same to Attribute Defn of VO
    decorateWithLazyHints(attributeDefImpl);
  } ...

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11g R1 PS3 + HR Schema]

How to run this sample?

Please run the dept.jspx. You may notice that default UI hints ( such as label, field width etc. ) are overridden with values from a dummy service( UIHintsService ).

Comments

  1. Can we control the DISPLAY_HINT property as well on the fly?

    Say, we want to hide the fields from Model layer, how can we achieve the same?

    ReplyDelete
  2. You can try Overriding ViewRowAttrHintsImpl::getDisplayHint(...)

    @Override
    public String getDisplayHint(LocaleContext locale) {
    return super.getDisplayHint(locale);
    }
    Please note that, if your UI is human built :-) [I mean, not model driven component like af:query/dynamic table etc.], then you may need to carry this hint to UI.
    rendered="#{bindings.DepartmentId.hints.displayHint=='Display'}"

    ReplyDelete
  3. Thanks Jobinesh.That helps.

    But customer wants to know, why for rendered property we need the EL expression in the jsff/jspx?
    Where as we dont do the same for readOnly/disabled property?
    Even though, we have dragged and dropped the VO as an af:panelFormLayout and the component af:inputText is VO bound.

    Is there any documentation or explanation available to convince the customer?They dont want to put manually a rendered EL expression to all 50 UI fields they have in their JSFF/JSPX?

    ReplyDelete
  4. For readOnly fileds, ADF binding layer is leveraging the feature supplied by JSF :). To make it clear, If you EL bind and input filed's value attribute with a manged bean without setter, the field would be rendered in read only mode by default. However this is applicable only for read only field. This is not carried over other properties such as rendered/disabled properties. There manual intervention is required.

    ReplyDelete
  5. Hey!

    Nice post.

    I have one problem with it.
    I'm using dvt:pivotTable for displaying some data. And pivot table has this good feature of pivoting data around (no shit). :D Inside dvt:pivotTable there is dvt:headerCell and every header cell has its own label. Now I want to dynamically set this label based on data inside that table. I have tried change label property on my view's attribute UI Hints (to some static text) to test it if it works. And it works. Now I want to set label programmatically and I have override createViewRowAttrHints method inside my ViewRowImpl and I have created new class which extends ViewRowAttrHintsImpl and overrides every method (including getLabel) of its super class. On every overriden method I set a breakpoint and here mystery begins. When I run the page none of overriden methods isn't called. If I set breakpoint at constructor it stops ok. Now my question is there any possibility that pivot table works differently with attribute hints? Or am I done something wrong?

    Regards

    ReplyDelete
  6. Hi.
    good sample.
    I've tested the sample and works fine with a form but if you drag a table, labels of the columns are painted before that createViewRowAttrHints.
    Thanks in advance

    JDev version: 11.1.2.1.0

    ReplyDelete
  7. Hi Jobinesh,

    I've a requirement in which I need to hide one of my VO's fields in the query panel's add_fields when used with one of the view criteria, and it should get displayed with the other view criteria.

    We tried to set the rendered property to 'never' for the field in the view criteria, but it doesn't work. Also tried overriding 'createViewRowAttrHints()' and when set the disply hint property as
    propMap.put(AttributeHints.ATTRIBUTE_DISPLAY_HINT , AttributeHints.ATTRIBUTE_DISPLAY_HINT_HIDE);

    Gives me
    javax.el.PropertyNotFoundException: Target Unreachable, '1' returned null
    at com.sun.el.parser.AstValue.getTarget(Unknown Source)
    at com.sun.el.parser.AstValue.isReadOnly(Unknown Source)

    Any ideas to make it work ?

    Thanks in Advance.

    ReplyDelete
  8. You can see an example here
    http://jobinesh.blogspot.com/2011/07/overriding-display-at-run-time.html

    ReplyDelete
  9. Do you know if it is possible to add a custom UI hint to a view object?

    ReplyDelete
  10. Hi Jobinesh,
    I have a requirement where i need to change the label of VO attributes dynamically.
    With attriibuteDef , I am able to use only getLabel function. Is there any way to set label programtically/dynamically?

    ReplyDelete

Post a Comment