ShowTable of Contents
Table of contents |
Previous Page |
Next Page
In the Notes client Document Library application, users can create responses to library documents. In this page, we will add the possibility to create and display responses to a main document within the XPage enabled application. Responses to a main document will be created and displayed on the same XPage as the main document. This will be achieved by using the new possibilities of XPages, like multiple data sources on one XPage, and repeat controls.
We will conclude this tutorial with a better way to display the main documents in read mode by using a separate custom control.
Create responses
Create the custom control ccFormResponse
Create a new Custom Control,
ccFormResponse
Via the Data palette, define a data source:
Enter a computed value for the
Parent ID: requestScope.parentID
Drag a panel container control in the custom control and give it the name "panelResponse".
Drag the Subject and Body fields from the data palette into the panel. Set the type of the Body field to Rich text, and include a Submit button. Change the button label to "Reply".
Add a title label "Reply" and apply some styling to the custom control elements (set width and apply OneUI style classes)
Save and close the custom control.
Include the custom control in ccFormDocument
Instead of displaying the response form on a different page in the web browser, we will display it straight under the main document form. This way, readers of the library document can immediately post a reply.
Open
ccFormDocument
From the Controls palette, drag ccFormResponse and drop it on the very bottom of ccFormDocument (=under the debug info).
With ccFormResponse still selected within ccFormDocument, go to the tab All Properties in the Properties view, and enter a computed value for the "rendered" property:
Enter this Server Side JavaScript:
!dominoDoc.getDocument().isNewNote() && !dominoDoc.isEditable();
This will only display the response custom control if the main document is not a new document or if it is opened in edit mode.
Save and close ccFormDocument.
Finalize ccFormResponse
Now, we still need to do some finetuning in ccFormResponse:
Open
ccFormResponse
Select the toplevel in the outline (="Custom Control") and in the properties of the custom control, go to the All Properties tab.
Under data - data - dominoDocument[0], set the property
computeWithForm to onsave, and set the property
ignoreRequestParams to true.
It is essential to set the property ignoreRequestParams to true in order to work with multiple data sources and have one data source open in edit mode (=response) while the other stays in read mode (main document).
We also need to add some code to the "Reply" button:
In the onclick event, add this code:
dominoResp.getDocument().makeResponse(dominoDoc.getDocument())
In the Server Options, select "Partial Update" and select "panelResponse" as element to update.
Adapt the action buttons in ccFormDocument
Now, having 2 data sources on one XPage causes a side effect: the buttons of the type "Submit" in ccFormDocument save all data sources on the XPage. This means that, when a user clicks on the buttons "Save" or "Submit for Review" (both are of button type "Submit"), not only the main document is saved, but also the response form is submitted, creating a new response document (which will actually not be a response to the main document, because the makeResponse method was not called.) Event with ccFormResponse not being rendered, the data source is submitted.
The workaround for this, is to change the button type to "Button", and add an explicit save action to the button:
Select the "Save" button in ccFormDocument and change the button type from "Submit" to "Button".
In the Events view, add two simple actions to the onclick event:
- Save Document
- Open Page: Previous Page
Also change the button "Submit for Review": change the button type to "Submit" and in the onclick event, add a simple action "Save Document" between the existing actions "Execute Script" and "Open page".

Display responses
When you test the current response form by opening a library document in read mode, and submitting a reply, you notice that a blank new response form is opened within the same Xpage. It looks as if the submitted contents is lost. Actually, it isn't: a new response document was created and it is visible in the viewAllDocuments.xsp. But since the "Reply" button in ccFormResponse performs a partial update (of panelResponse), the same form is loaded again.
This is meaningful on condition that the response that was just created is visible in the XPage. Therefore, we will now provide a means to display submitted responses in the XPage. We will make use of a repeat control for this.
Create a custom control to display responses
Create a new custom control and give it the name "ccDisplayResponses"
Drag a Repeat container control into this custom control.
In the repeat control properties, add a Server Side JavaScript for iteration:
var doc = dominoDoc.getDocument();
doc.getResponses();
Under "Options" set the value of Collection name to "docRespDisplay"
With repeat controls, you can easily display data of a list of documents in a layout you define yourself. In the iteration, you can use simple data binding an select the view that contains the documents to iterate in, or you can specify a JavaScript that returns either a list of NotesDocument objects or a lis of Document ID's.
The Collection name is the name of the instance variable you will use to display individual values.
Drag a panel into the Repeat control and call it "panelRepeat"
Set the panel to Read-only, as it will only contain display information (Properties view, first tab, under visibility).
Drag a computed field into the panel, and call it "respSubject". It will be used to display the subjects of the responses.
Give it the following value:
docRespDisplay.getItemValueString("Subject")
Save and close ccDisplayResponses.
Add the response list to ccFormDocument
Open ccFormDocument and drag ccDisplayResponses above ccFormResponse.
The Outline view of ccFormDocument now looks like this:
If you now would open an existing document that has multiple responses, you would see the subjects of each reply listed.
In order to immediately see newly added replies within ccFormDocument, we need to create a container that contains both the ccDisplayResponses and ssFormResponse, and when submitting a reply, perform a partial update of this container.
In ccFormDocument, add a new panel container control on the bottom and name it "panelResponseThread".
Via the Outline view, drag both ccDisplayResponses and ccFormResponse into this panel:
Save and close ccFormDocument.
Open ccFormResponse and select the "Reply" button.
In the onclick event, change the element for Partial Update: instead of selecting an element on the page, choose "Specify element by ID" and enter panelResponseThread:
Save and close ccFormResponse.
Test the result. When you now submit a reply to an existing library document, it's subject is immediately displayed in the list.

Enhance response display
Now we will add more fields to the response display list and present them in a neater way.
In ccDisplayResponses, add more computed fields:
Add a computed field above the subject, and make it return the name of the author of the reply:
var aName = session.createName(docRespDisplay.getItemValueString("From"));
aName.getCommon();
Under the subject, add another computed field with the date and time of creation as value
docRespDisplay.getCreated().getDateOnly() + " " + docRespDisplay.getCreated().getTimeOnly()
Add a third computed field to display the body contents. Since the body of the reply is rich text, it have to be converted to text. In order to do that, add a hidden computed field on the Response form in Notes (=the old-school Notes form) with the name "BodyText" and the value @Abstract([Rule1];256;"";"Body").
The third computed field in the repeat control in ccDisplayResponses can now have as value:
docRespDisplay.getItemValueString("BodyText")
Now, add some styling by adding container controls (add <div> tags in the Source view) and assigning them OneUI style classes of your choice.
For example, the Source code of panelRepeat could look like this:
<xp:panel id="repeatPanel" readonly="true">
<div class="lotusForum">
<div class="lotusPost">
<div class="lotusPostAuthorInfo">
<div class="lotusPostAvatar">
<xp:text escape="true"id="computedField2">
<xp:this.value>
<![CDATA[#{javascript:var aName = session.createName(docRespDisplay.getItemValueString("From"));
aName.getCommon();}]]></xp:this.value>
</xp:text>
</div>
</div><!--end author info-->
<div class="lotusPostContent">
<h4>
<xp:text>
<xp:this.value>
<![CDATA[#{javascript:docRespDisplay.getItemValueString("Subject")}]]></xp:this.value>
</xp:text>
</h4>
<div class="lotusMeta">
<xp:text>
<xp:this.value>
<![CDATA[#{javascript:docRespDisplay.getCreated().getDateOnly() + " " + docRespDisplay.getCreated().getTimeOnly()}]]>
</xp:this.value>
</xp:text>
</div>
<div class="lotusPostDetails">
<xp:text escape="true"
id="computedField1">
<xp:this.value><![CDATA[#{javascript:docRespDisplay.getItemValueString("BodyText")}]]>
</xp:this.value>
</xp:text>
</div>
</div><!--end postContent-->
</div>
</div>
</xp:panel>
The result looks like this:

Read and edit mode custom controls
So far, he main library document input form has been optimized for new data entry / editing, and not for viewing in read mode. It looks far from elegant in read mode. In order to have more control over the look and feel of the library document in read mode, without interfering with the input form, separate custom controls will be created to display the document in edit and read mode, and the edit and read custom controls will be rendered conditionally then.
Create separate custom controls
Create a new custom control,
ccFormDocumentEdit
Open the existing ccFormDocument and cut the table containing the main document fields. You can select this table in the Outline view, and once it is selected, you can right-click on the edge of the table in the editor and use the right-menu option "cut".
Paste the table in the blank ccFormDocumentEdit and save the custom control.
In ccFormDocument, drag ccFormDocumentEdit into the edit area, on top: it now replaces the form table. The result is identical as before.
Save ccFormDocument.
Create a new custom control:
ccFormDocumentRead
Drag a panel container control in it.
Add a text label to this panel "Library document", just to have something visible. We will add more content further on.
Save ccFormDocumentRead.
Display custom controls conditionally
Open ccFormDocument and drag ccFormDocumentRead in the custom control, above ccFormDocumentEdit.
Select ccFormDocumentRead in the Outline and in the properties, add a computed visibility:
Do the same form ccFormDocumentEdit, but set it to display in edit mode:
The main document is now displayed with the approprate custom control in function of read/edit mode.
Display content in ccFormDocumentRead
In order to display data in controls, we need to bind the controls to the underlying document. Data binding can be either done globally in the Data palette, in the Custom Control properties (data tab), or individually for each data display control.
Definining the data source globally makes it easy to do the binding for the individual controls, because you can simply select the data source from the dropdown. The only drawback is that you need to remove the data source afterwards in order to make the edit button work: the data source needs to be defined at XPage level, instead of at custom control level, or the users will have to click twice on the edit button (this was discussed earlier, on the page about Form Design)
We will define the data source globally, and remove it later.
In the Custom Control properties, Data tab, add a data source of type "Domino Document" and give it the same name as the data source defined in the XPage formDocument:
dominoDoc Reason: we wil remove this data source later on, and just need a way to set-up the right binding for our individual controls.
Leave the default action to "Create Document". This doesnt make much sense (you would expect to make it "Open Document", but then you would need to specify a document ID.)
Now you can add content in the form of computed fields:
Add a computed field
cfFormTitle and bind it to bind to
dominoDoc.Subject
in the Source view, place <h2> tags around this field:
<h2>
<xp:text escape="false" id="cfFormTitle"
value="#{dominoDoc.Subject}">
</xp:text>
</h2>
Add an additional computed field, under cfFormTitle, and call it
cfAuthorInfo.
Change the type to "Html". This allows us to write html in the value:
var aName = session.createName(dominoDoc.getDocument().getItemValueString("From"));
"By <a class='lotusFilter'>" + aName.getCommon() + "</a> on " + dominoDoc.getDocument().getCreated().getDateOnly();
The idea is that the author name is clickable and when clicking on it, a list of documents from this author is displayed (the actual link has not been added yet: to be completed later on),
Add a Style class to the computed field:
Additonally, add a rich text field to the panel and bind it to
dominoDoc.Body.
In order to make this field read-only, we could set the Readonly flag in the Rich Text properties, but it is better to set this property globally, at custom control level:
Custom Control Properties: data: data: readonly: true.
Add a file download control to display attachments.
Add action buttons to ccFormDocumentRead
Move the Edit button from ccFormDocumentEdit to ccFormDocumentRead and copy and paste the Cancel link.
In order to make the edit button work, it has to be linked to the data source defined within the XPage, rather than the one defined in the custom control. (=limitation in Domino 851, discussed before).
Therefore, remove the data source on ccFormDocumentRead.
The edit button will now work.
Summary
This page explained how to work with different data sources in one XPage, and how to display information form a collection of response documents using a repeat control. And finally, we added a different interface to display the document form content in read mode.
Tutorial summary
This tutorial ends here. It demonstrated how to web enable an existing Notes client application by using XPages.
The XPage Document Library sample application clearly is not completed yet: views need to be added, the workflow needs to be completed, title bar navigation added, etc... Rather than delivering a read-for-use application, this tutorial intended to provide you with all major stepstones to web enable your own Notes client applications.
