Over the last day or so a small change in behaviour between 11.1.2.n releases of ADF and earlier versions has come to my attention. This has concerned the default sizing of the dialog that the framework automatically generates to handle the display of JSF messages being handled by the <af:messages> component. Unlike a normal popup, you don't have a physical <af:dialog> or <af:window> to set the sizing on in your page definition, so you're at the mercy of what the framework provides. In this case the framework now defines a fixed 250x250 pixel content area dialog for these messages, which can look a bit weird if the message is either very short, or very long. Unfortunately this is not something that you can control through the skin, instead you have to be a little more creative.
Here's the solution I've come up with. Unfortunately, I've not found a supportable way to reset the dialog so as to say just size yourself based on your contents, it is actually possible to do this by tweaking the correct DOM objects, but I wanted to start with a mostly supportable solution that only uses the best practice of working through the ADF client side APIs.
The Technique
The basic approach I've taken is really very simple. The af:messages dialog is just a normal richDialog object, it just happens to be one that is pre-defined for you with a particular known name "msgDlg" (which hopefully won't change). Knowing this, you can call the accepted APIs to control the content width and height of that dialog, as our meerkat friends would say, "simples" 1
The JavaScript
For this example I've defined three JavaScript functions.
The first does all the hard work and is designed to be called from server side Java or from a page load event to set the default.
The second is a utility function used by the first to validate the values you're about to use for height and width.
The final function is one that can be called from the page load event to set an initial default sizing if that's all you need to do.
Function resizeDefaultMessageDialog()
/**
* Function that actually resets the default message dialog sizing.
* Note that the width and height supplied define the content area
* So the actual physical dialog size will be larger to account for
* the chrome containing the header / footer etc.
* @param docId Faces component id of the document
* @param contentWidth - new content width you need
* @param contentHeight - new content height
*/
function resizeDefaultMessageDialog(docId, contentWidth, contentHeight) {
// Warning this value may change from release to release
var defMDName = "::msgDlg";
//Find the default messages dialog
msgDialogComponent =
AdfPage.PAGE.findComponentByAbsoluteId(docId + defMDName);
// In your version add a check here to ensure we've found the right object!
// Check the new width is supplied and is a positive number, if so apply it.
if (dimensionIsValid(contentWidth)){
msgDialogComponent.setContentWidth(contentWidth);
}
// Check the new height is supplied and is a positive number, if so apply it.
if (dimensionIsValid(contentHeight)){
msgDialogComponent.setContentHeight(contentHeight);
}
}
Function dimensionIsValid()
/**
* Simple function to check that sensible numeric values are
* being proposed for a dimension
* @param sampleDimension
* @return booolean
*/
function dimensionIsValid(sampleDimension){
return (!isNaN(sampleDimension) && sampleDimension > 0);
}
Function initializeDefaultMessageDialogSize()
/**
* This function will re-define the default sizing applied by the framework
* in 11.1.2.n versions
* It is designed to be called with the document onLoad event
*/
function initializeDefaultMessageDialogSize(loadEvent){
//get the configuration information
var documentId = loadEvent.getSource().getProperty('documentId');
var newWidth = loadEvent.getSource().getProperty('defaultMessageDialogContentWidth');
var newHeight = loadEvent.getSource().getProperty('defaultMessageDialogContentHeight');
resizeDefaultMessageDialog(documentId, newWidth, newHeight);
}
Wiring in the Functions
As usual, the first thing we need to do when using JavaScript with ADF is to define an af:resource in the document metaContainer facet
<af:document>
....
<f:facet name="metaContainer">
<af:resource type="javascript" source="/resources/js/hackMessagedDialog.js"/>
</f:facet>
</af:document>
This makes the script functions available to call.
Next if you want to use the option of defining an initial default size for the dialog you use a combination of <af:clientListener> and <af:clientAttribute> tags like this.
<af:document title="MyApp" id="doc1">
<af:clientListener method="initializeDefaultMessageDialogSize" type="load"/>
<af:clientAttribute name="documentId" value="doc1"/>
<af:clientAttribute name="defaultMessageDialogContentWidth" value="400"/>
<af:clientAttribute name="defaultMessageDialogContentHeight" value="150"/>
...
Just in Time Dialog Sizing
So what happens if you have a variety of messages that you might add and in some cases you need a small dialog and an other cases a large one? Well in that case you can re-size these dialogs just before you submit the message. Here's some example Java code:
FacesContext ctx = FacesContext.getCurrentInstance();
//reset the default dialog size for this message
ExtendedRenderKitService service =
Service.getRenderKitService(ctx, ExtendedRenderKitService.class);
service.addScript(ctx, "resizeDefaultMessageDialog('doc1',100,50);");
FacesMessage msg = new FacesMessage("Short message");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
ctx.addMessage(null, msg);
So there you have it. This technique should, at least, allow you to control the dialog sizing just enough to stop really objectionable whitespace or scrollbars.
1 Don't worry if you don't get the reference, lest's just say my kids watch too many adverts.