Read the associated Blog Post: XPages Compatible Dojo Dialog Reusable Component
This sample demonstrates how to use the
com.ZetaOne.widget.Dialog class to display an XPages
compatible dijit.Dialog box. The sample goes beyond
the basics of just displaying the dialog to illustrate
how to partial refresh to the server to fetch data
based on a user's selection, then create and display
the dialog on the fly.
Process Flow:
- User clicks a link related to a specific document
- Client-side script then places the UNID of the associated document into a hidden field
- The browser submits a partial refresh to the server which includes the hidden field with the UNID
- The server generates the markup required to edit the document, and is returned with the partial refresh
- The onComplete of the partial refresh takes the generated markup, creates a dialog box, and places
the content from the partial refresh into the dialog.
- The User edits the data, and clicks Ok, Cancel, or the dialog's (X)
- The markup is moved back to its proper position in the DOM
- If the user clicked OK, the document is posted back to the server, and the document is saved
- The onComplete of the partial refresh to post the data then does a partialRefreshGet() to refresh the
contents of the document list.
- The dialog is destroyed and de-registered so the next user selection can re-create the dialog box without generating an error.
Below is a data set surfaced by using an xp:repeat
control. Each line in the data-set represents a
different document. To display and edit the document
in a dijit.Dialog, click document's link.
Working Example
XPage Source Code for this Sample
For display purposes, extra spaces have been placed between ]] ${ and #{<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" dojoParseOnLoad="true"
dojoTheme="true">
<xp:this.resources>
<xp:styleSheet href="/base.css"></xp:styleSheet>
<xp:dojoModule name="dijit.form.Button"></xp:dojoModule>
<xp:script src="/DialogComponent.js" clientSide="true"></xp:script>
</xp:this.resources>
<xp:panel styleClass="workingSample">
<xp:this.data>
<xp:dominoView var="sampleData"
viewName="sample-data-view">
</xp:dominoView>
</xp:this.data>
<xp:repeat value="" var="sampleDoc" id="dataView" style="height:250px;overflow:auto;"
indexVar="sampleIndex">
<div class="dataBlock">
<xp:link text=""
id="link1">
<xp:eventHandler event="onclick"
submit="true" refreshMode="partial"
refreshId="refreshDocumentRegion">
<xp:this.script><![CDATA[
// This script sets the hidden field "editDocId" equal to the UNID of the
// document the user just clicked on. Because editDocId is connected to
// viewScope.editDocId, when we partial refresh refreshDocumentRegion, the
// current document that is getting edited will change.
dojo.query('[id$="editDocId"]')[0].value = '# {javascript:sampleDoc.getDocument().getUniversalID();}'
] ]></xp:this.script>
<xp:this.onComplete><![CDATA[
// After the partial refresh has completed, we can display the dialog to the user.
// We are going to dynamically create the dialog rather than use HTML Markup
// via dojoType so we can immediately show it to the user.
// create the dialog...
var userDialog = new com.ZetaOne.widget.Dialog({
title: 'XPages Compatible Dojo Dialog Reusable Component',
id: 'sampleDialogEditor',
style: {
width: '400px',
height: '100px'
},
onCancel: function() {
// This function runs when the user clicks the (X) at the top right of the dialog
// Here we are going to move the data back to its proper spot in the DOM.
var editDocumentRegion = dojo.query('[id$="editDocumentRegion"]', this.domNode)[0];
dojo.query('[id$="refreshDocumentRegion"]')[0].appendChild(editDocumentRegion);
this.destroyRecursive(false);
}
});
// place the dialog into the DOM, and initialize it
dojo.body().appendChild(userDialog.domNode);
userDialog.startup();
userDialog.show();
var editRegion = dojo.query('[id$="editDocumentRegion"]')[0];
dojo.style(editRegion, { display: 'block' });
userDialog.containerNode.appendChild(editRegion);
] ]></xp:this.onComplete>
</xp:eventHandler>
</xp:link>
</div>
</xp:repeat>
<xp:div id="div1">
<xp:inputHidden id="inputHidden1"
value="" immediate="true" />
<xp:panel id="panel1"
style="position:relative;width:400px;height:80px;display:none;">
<xp:this.data>
<xp:dominoDocument var="sampleEditableDoc"
action="editDocument"
documentId=""
formName="sample-data">
</xp:dominoDocument>
</xp:this.data>
<xp:text value="Document Title"
style="position:absolute:top:10px;left:20px;" />
<xp:inputText id="inputText1"
style="position:absolute:top:10px;left:80px;width:190px;"
value="" />
<xp:button dojoType="dijit.form.Button"
style="position:absolute;top:25px;left:260px;" id="button2"
value="OK">
<xp:eventHandler event="onclick"
submit="true" refreshMode="partial"
refreshId="refreshDocumentRegion">
<xp:this.script><![CDATA[
// this client side script will run before the partial refresh executes. Here
// we will move the contents of the partial refresh back to the proper place,
// and destroy the dialog so that it can be garbage collected, and the
// registry will not prevent it from getting re-created on the next user-edit.
var dialog = dijit.byId('sampleDialogEditor');
var editRegion = dojo.query('[id$="editDocumentRegion"]', dialog.containerNode)[0];
dojo.style(editRegion, { display: 'none' });
dojo.query('[id$="refreshDocumentRegion"]')[0].appendChild(editRegion);
dialog.hide();
dialog.destroy(false);
// instruct the partial refresh to continue to save the document.
return true;
] ]></xp:this.script>
<xp:this.action>
<xp:saveDocument></xp:saveDocument>
</xp:this.action>
<xp:this.onComplete><![CDATA[
XSP.partialRefreshGet('view:_id1:_id52:dataView');
] ]></xp:this.onComplete>
</xp:eventHandler>
</xp:button>
<xp:button dojoType="dijit.form.Button"
style="position:absolute;top:25px;left:310px;" id="button3"
value="Cancel">
<xp:eventHandler event="onclick"
submit="true" refreshMode="partial"
refreshId="refreshDocumentRegion">
<xp:this.script><![CDATA[
// this client side script will run before the partial refresh executes. Here
// we will move the contents of the partial refresh back to the proper place,
// and destroy the dialog so that it can be garbage collected, and the
// registry will not prevent it from getting re-created on the next user-edit.
var dialog = dijit.byId('sampleDialogEditor');
var editRegion = dojo.query('[id$="editDocumentRegion"]', dialog.containerNode)[0];
dojo.style(editRegion, { display: 'none' });
dojo.query('[id$="refreshDocumentRegion"]')[0].appendChild(dojo.query('[id$="editDocumentRegion"]', dialog.containerNode)[0]);
dialog.hide();
dialog.destroy(false);
// instruct the partial refresh to continue to save the document.
return true;
] ]></xp:this.script>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:div>
</xp:panel>
</xp:view>Client-Side JavaScript Code for this Sample
// DialogComponent.js
dojo.require('dojo._base._loader.loader_nsf');
dojo.requireFromNsf('com.ZetaOne.widget.Dialog', window.location.pathname.split('.nsf')[0] + '.nsf/');
// com.ZetaOne.Widget.Dialog
dojo.provide('com.ZetaOne.widget.Dialog');
dojo.require('dijit.Dialog');
(function(){
dojo.declare("com.ZetaOne.widget.Dialog", dijit.Dialog, {
postCreate: function(){
this.inherited(arguments);
dojo.query('form', dojo.body())[0].appendChild(this.domNode);
},
_setup: function() {
this.inherited(arguments);
if (this.domNode.parentNode.nodeName.toLowerCase() == 'body')
dojo.query('form', dojo.body())[0].appendChild(this.domNode);
}
})
}());