I would like share my experience on using Javascript in ADF. I have
seen many times developer makes some common mistake while using
Javascript with ADF without properly understanding it. At the time of
development, may be all look good in terms of functionality but
sometimes it introduces performance and maintenance issues. ADF Faces is
an Ajax-enabled rich JavaServer Faces component framework that uses
JavaScript to render client-side components, implement rich component
functionality, validate user input and convert user data input. ADF
exposes public javascript APIs which developer can use instead of
directly doing DOM manipulation. DOM manipulation is something which
developer should not start with before looking all other options
provided by ADF public Javascript APIs.
In ADF, The majority of the UI components are rendered in HTML, that is generated on the server side for the request. Every ADF UI component is represented by two types of javascript classes - a public component object and an internal peer object. The public objects is used by the developers when programming on the ADF Faces client side. Peer objects help in rendering logic and hide the browser specific DOM implementation code. For every ADF UI component object, there will be the corresponding object in server. But, it's not necessary always to have a ADF javascript object on the client side, we will go in detail on this later.
JS is all about functions and objects. Even functions are objects in JS and you can assign properties to the functions as you do for objects. JS has first-class functions meaning it supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables. JS supports prototypal inheritance which is different than classical inheritance. Each ADF UI component has a corresponding JS object and has a root object as AdfObject. Each ADF UI JS object follow the name convention and prefix by "Adf" and the corresponding server component doesn't have the prefix. For Ex: AdfRichPopup
Client Side JS Object Heirarchy
Server Side Java Class Heirarchy
Public methods that are exposed by the component JS object can be used to manipulate the component properties and do operations. For most of the action listeners and events both server side and client side operations exists but it may not be the case everytime. For Ex: To show, hide and cancel a popup both server and client side operation exist. The
Enough theory, let's see some examples where we can apply these concepts -
1. Never use ADF Internal JavaScript objects
JS doesn't have any package structures like Java classes. Based on the hierarchical object structure it create package like structure to access the object. ADF Faces make these things simple by applying the naming conventions and make it look like Java so it's easy to understand. In ADF Faces, two package structures are used: oracle.adf.view.js and oracle.adfinternal.view.js. The oracle.adfinternal.view.js package contains those JavaScript objects that should only be used internally by the ADF Faces component framework. I have seen many times developers using internal packages and then blaming the framework later when it doesn't work when you migrate to new releases or if some patches applied. Changes to internal packages are applied without any notice.
For Ex: AdfPanelStretchLayout
Internal JS Object
2. Finding ADF Component on the Client
I have seen many times developers using JQuery/JS to find the ADF component by id in the DOM by looking at the generated HTML For Ex: document.getElementById("itemId"). This is not the correct approach because the HTML generated may change based on the ADF UI component implementation.
As I mentioned before, the component hierarchy on the server is same as the hierarchy of ADF Faces components on the client. But, it's not necessary to have the client object for every ADF Faces component but will have the server side generated html. To make sure, client object exist there are two ways to do that -
After making sure ADF client object exist, move on to find the component by Id using ADF Javascript objects. AdfPage.PAGE object exposes three methods to find the component -
Reference - http://www.oracle.com/technetwork/developer-tools/jdev/1-2011-javascript-302460.pdf
In ADF, The majority of the UI components are rendered in HTML, that is generated on the server side for the request. Every ADF UI component is represented by two types of javascript classes - a public component object and an internal peer object. The public objects is used by the developers when programming on the ADF Faces client side. Peer objects help in rendering logic and hide the browser specific DOM implementation code. For every ADF UI component object, there will be the corresponding object in server. But, it's not necessary always to have a ADF javascript object on the client side, we will go in detail on this later.
JS is all about functions and objects. Even functions are objects in JS and you can assign properties to the functions as you do for objects. JS has first-class functions meaning it supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables. JS supports prototypal inheritance which is different than classical inheritance. Each ADF UI component has a corresponding JS object and has a root object as AdfObject. Each ADF UI JS object follow the name convention and prefix by "Adf" and the corresponding server component doesn't have the prefix. For Ex: AdfRichPopup
Client Side JS Object Heirarchy
Server Side Java Class Heirarchy
Public methods that are exposed by the component JS object can be used to manipulate the component properties and do operations. For most of the action listeners and events both server side and client side operations exists but it may not be the case everytime. For Ex: To show, hide and cancel a popup both server and client side operation exist. The
popupOpening is a
client only event that can be canceled. If this event is canceled in a client-side listener, the popup will not be shown. The PopupFetchEvent
is one of two server-side popup events but doesn't have a corresponding client event. The custom client event listeners can invoke JavaScript that raises a CustomEvent
that is handled by a af:serverListener
. See the Javadocs - http://docs.oracle.com/cd/E21764_01/apirefs.1111/e10684/oracle/adf/view/rich/component/rich/RichPopup.html for details.Enough theory, let's see some examples where we can apply these concepts -
1. Never use ADF Internal JavaScript objects
JS doesn't have any package structures like Java classes. Based on the hierarchical object structure it create package like structure to access the object. ADF Faces make these things simple by applying the naming conventions and make it look like Java so it's easy to understand. In ADF Faces, two package structures are used: oracle.adf.view.js and oracle.adfinternal.view.js. The oracle.adfinternal.view.js package contains those JavaScript objects that should only be used internally by the ADF Faces component framework. I have seen many times developers using internal packages and then blaming the framework later when it doesn't work when you migrate to new releases or if some patches applied. Changes to internal packages are applied without any notice.
For Ex: AdfPanelStretchLayout
Internal JS Object
2. Finding ADF Component on the Client
I have seen many times developers using JQuery/JS to find the ADF component by id in the DOM by looking at the generated HTML For Ex: document.getElementById("itemId"). This is not the correct approach because the HTML generated may change based on the ADF UI component implementation.
As I mentioned before, the component hierarchy on the server is same as the hierarchy of ADF Faces components on the client. But, it's not necessary to have the client object for every ADF Faces component but will have the server side generated html. To make sure, client object exist there are two ways to do that -
- By setting clientComponent=true property on UI Component declaratively using property inspector
- If the UI component has af:clientListener attached to it then automatically it client object is generated
After making sure ADF client object exist, move on to find the component by Id using ADF Javascript objects. AdfPage.PAGE object exposes three methods to find the component -
- findComponent
- findComponentByAbsoluteId
- findComponentByAbsoluteLocator
Reference - http://www.oracle.com/technetwork/developer-tools/jdev/1-2011-javascript-302460.pdf