Dialog windows in XMS Web Console

This is an example of how to define dialog windows in XMS Web Console.

Main Page

  • Create a p:commandButton that contains following elements:
    • action or actionListener attribute that defines action to execute
    • onclick ajax hooks - used to present ajax loader window and present dialog when reload action ends
    • resetInput - used to reset existing form inputs
  • Include xhtml file with the dialog window defined

Note that if the dialog only sends a request when accepted, and does not need to re-render itself upon showing up (e.g. a delete confirmation), the commandButton calling <<dialog_widget_name>>.show() should have attributes type="button", so that no (empty) AJAX request is sent.

Dialog Page

  • Create a p:subview with id
  • Create a p:dialog with following elements:
     
    • id attribute
    • header attribute
    • widgetVar attribute - used to define name of the widget (accessible from js)
    • dynamic attribute set to true or false - if you set dynamic to true, the content of the dialog will not be rendered until it is shown for the first time in the current view
    • onShow="AMG.XLcloud.Dialogs.onshow(<<widgetVar>>)"
    • closeOnEscape="true" is recommended
  • Create ui:decorate with template attribute set to: "/layout/dialog-decorator.xhtml" 
  • If the dialog is dynamic you need to specify ui: param named "dynamicDialogId" that contains component id of the dialog.
  • Create ui:define named "dialog-body" that defines the body of the dialog
  • Create ui:define named "dialog-controls" that defines the buttons of the dialog (e.g. "Save")
  • "Cancel" button, if present, should generally have type="button", so that it does not send an AJAX request
  • "OK" button should have widgetVar="<<someName>>" onclick="<<someName>>.disable();" and oncomplete="<<someName>>.enable();" to be disabled on click

Some dialogs require special behavior, and its possible to customize them by passing additional parameters to the AMG.XLcloud.Dialogs.onshow() function. The declaration of this function is as follows.

function(widgetVar, alwaysMaxWidth, alwaysMaxHeight, suppressScrollbars);

Param name

Default value

Description

widgetVarnullwidgetVar of the dialog, required
alwaysMaxWidthfalseshould content always have maximum width
alwaysMaxHeightfalseshould content always have maximum height
suppressScrollbarsfalseif true, scrollbars will not appear on the content div

Note that it is not possible to disable only vertical or horizontal scrollbars without affecting the other. It is a design decision. Explanation: The suppressScrollbars param is generally used when you need an element with width="100%" and/or height="100%". This means, that to disable scrollbars, overflow value 'visible' is used, because using 'hidden' causes the element to be clipped. However the W3C specification says: "The computed values of ‘overflow-x’ and ‘overflow-y’ are the same as their specified values, except that some combinations with ‘visible’ are not possible: if one is specified as ‘visible’ and the other is ‘scroll’ or ‘auto’, then ‘visible’ is set to ‘auto’." This means that it's not possible to get one overflow 'visible' and the other 'auto'.

The parameters can be used to solve several issues. For example:

  • The dialog is rendered too narrow - use alwaysMaxWidth parameter.
  • You want an HTML element to fill the dialog content completely, but using width="100%" and/or height="100%" causes scrollbars to appear - use suppressScrollbars to disable them.
  • The content of the dialog dynamically changes its height (e.g. the dialog contains toggleable panels) - you can use alwaysMaxHeight - when the content expands and becomes larger than the dialog, scrollbar will appear, and the dialog will be properly centered.

Example
layerList.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
  xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui" xmlns:c="http://java.sun.com/jsp/jstl/core">
 
      <p:commandButton value="#{msg['layer.create']}" title="#{msg['layer.create']}" icon="ui-icon-plus" iconPos="right"
        onclick="AMG.XLcloud.Dialogs.onclick(newLayerDialogWidget);"
        actionListener="#{createLayerBean.initNew(template.id)}" process="@this">
      <p:resetInput target=":contentertert:new-layer-subview:new-layer-form" />
    </p:commandButton>

    <p:outputPanel id="layer-dialogs">
      <ui:include src="/dialogs/newLayer.xhtml" />
    </p:outputPanel>
</ui:composition>

/dialogs/newLayer.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
  xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui" xmlns:c="http://java.sun.com/jsp/jstl/core">
  <f:subview id="new-layer-subview">
    <p:dialog id="new-layer-dialog" header="#{msg['layer.create']}" widgetVar="newLayerDialogWidget"
      modal="true" draggable="false" position="center" resizable="false" dynamic="true" closeOnEscape="true"
      onShow="AMG.XLcloud.Dialogs.onshow(newLayerDialogWidget, false, true)">
      
      <ui:decorate template="/layout/dialog-decorator.xhtml">
        <ui:param name="dynamicDialogId" value="#{component.namingContainer.clientId}:new-layer-dialog" />

         <ui:define name="dialog-body">
         <p:outputPanel id="new-layer-form" layout="block" styleClass="entity-details-panel form-grid-container">
            <! define body of the dialog >
         </p:outputPanel>
        </ui:define>
        <ui:define name="dialog-controls">
          <! define dialog buttons >
        </ui:define>
      </ui:decorate>
    </p:dialog>
  </f:subview>
</ui:composition>

Custom conventions

  1. Ajax Loader
    Primefaces component works that way, that the content of the component is rendered on the server side and returned to the client. This sometimes take some time especially when the content is lazy loaded from XMS-API. We use onclick="AMG.XLcloud.Dialogs.onclick(<<widgetVar>>);" ajax hooks to present ajax loader window.

loader.png

2. Different render phases of jsf and primefaces components
We use primefaces components (p-prefixed) and jsf (ui-prefixed) together. This cause some problems, because they are rendered in different phases. Even if the dialog is dynamic, all ui commands will be executed earlier, since jsf commands are invoked in the earlier phase. Solution of this problem is already included in dialog-decorator.xhtml.  We use <c:if>...</c:if> tags to wrap content which should not be rendered when the dialog is dynamic and not initialized. In order to check whether the dialog is already presented or not, we need dialog id, which is passed trough dynamicDialogId. If this parameter is not specified, content is rendered every time without any checking.

3. Messages in dialog windows
Global messages are presented in the page layout, but in most cases they are behind the dialog window and they are not visible. We decided to add a message container to each dialog page. This is provided by wrapping the dialog content with dialog-decorator, which automatically adds a message container to the top of each dialog content.

dialog_error.png


This wiki is licensed under a Creative Commons 2.0 license
XWiki Enterprise 5.4.6 - Documentation - Legal Notice

Site maintained by