Domino Document cannot be opened twice on public access xpage - xpages

I have an Xpage with access set to public for clients to fill in a form. When I send the client the link to the page and they open it for the first time. Everything runs smoothly. However, if they close the browser and click on the link again they receive this error:
{Unexpected runtime error
The runtime has encountered an unexpected error.
Error source
Page Name:/xpClientForm.xsp
Exception
Could not open the document
Invalid universal id}
I am using a switch facet to cycle between forms depending on the client type.
The domino document id is being stored in a sessionScope beforepageload and the document dynamically computes it based on that sessionScope variable.
Here is the code:
SessionScope assignment on beforepageload
var cData = getClientData(id);
sessionScope.docId = cData.docID;
Document datasource
<xp:panel style="height:100px" id="pnlDocData">
<xp:this.data>
<xp:dominoDocument var="document1"
formName="frmA" action="editDocument"
documentId="#{javascript:sessionScope.docID;}" scope="request">
</xp:this.data>
</xp:panel>
However when i execute this custom control on a page that does not have public access. It runs fine with no issues irrespective of how many times i open the link.
Any help will be greatly appreciated.

You need to set ignoreRequestParams="true" on the dominoDocument datasource. Otherwise it's using the document ID in the URL or trying to create a new document, which the user probably doesn't have access to do.
Computing the document ID is the less common scenario, which is using the URL for document location is the default.

Related

Binding data to a single document from multiple custom controls

I have an Xpage with multiple custom controls that make up a form. When I click the submit button I get a multiple documents saving the multiple custom control data as a separate document.
I have the data sources configured at the custom control level.
How can I make it that all the custom control save the data to one single document?
Thanks,
Just put them on the XPage. If you use a variable name (e.g. for a datasource, a dataContext etc), the runtime will just look outwards from the current component in the hierarchy to find the relevant object. If you're having problems thinking of the XML source code in a three-dimensional way, the Outline view is good for this.
So from within a Custom Control, you can reference a datasource on the XPage, as long as it is defined in an ancestor of the custom control on the XPage or is a previous sibling. So in the structure below, document1 will be accessible from anywhere in the ccFriends custom control.
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Profile">
</xp:dominoDocument>
</xp:this.data>
<xc:ccFriendsAlt></xc:ccFriendsAlt>
You can also pass the data source object as a custom property to the custom control if you can't follow Paul's suggestion of keeping the same variable name for your data source.
http://lpar.ath0.com/2013/04/22/passing-document-data-objects-to-xpages-custom-controls/

xpages display a new doc. inside a dialog

i have an issue that it gives me some headache lately.
In my XPage there is a view displaying some docs ( let say Pdoc as datasource ) and I open/create them inside a <xe:dialog>. This dialog has only Pdoc declared as datasource, and it inherits some values from the Xpage datasrouce. My clickable column formula is:
// some var declarations
var formName = rowData.getDocument().getItemValueString("Form");
if ( formName == "fmP" )
{ viewScope.put("dlgDocUnid", pe.getUniversalID())
getComponent("exampleDialog").show(); }
On the same XPage, I can create a new Pdoc using the same dialog via a button, New Pdoc.
The problem is: when I opened an existing Pdoc and then just save it or close it, and after I use the button to create a newNote => the old / previous ( already saved Pdoc ) is showed...
If firstly I just created a new note Pdoc, it works, and it is showing a new empty Pdoc.
My dialog data code:
<xp:this.data>
<xp:dominoDocument var="Pdoc" formName="fmPersContact"
ignoreRequestParams="true" scope="request" action="editDocument">
<xp:this.documentId><![CDATA[#{javascript:viewScope.get("dlgDocUnid");}]]></xp:this.documentId>
</xp:dominoDocument>
</xp:this.data>
I use the .documentId for the open method from the viewPanel. I think here is the problem. I think ,( I'm not sure), I should compute this documentId in such way that when I create a newNote this documentID shouldn't be anymore the viewScope.get("dlgDocUnid").
Thanks for your time.
If I understood correctly, you have defined two data sources within the XPage and you try to consume them in the dialog, right? Instead I suggest defining a single data source within a panel inside the xe:dialog.
I have blogged about a similar example. In this example, tooltip dialog has been used but it's the same logic, you might replace xe:tooltipDialog with xe:dialog.
http://lotusnotus.com/lotusnotus_en.nsf/dx/mini-patterns-for-xpages-parameter-editing-with-dialogs-1.htm
The idea here is that you use a viewScope variable named noteId. To open an existing document, set this variable to the note id of the existing document. To create a new document, the value will be set as NEW. Then you define the data source within the dialog according to this variable:
<xe:dialog>
<xp:panel style="width:500.0px">
<xp:this.data>
<xp:dominoDocument
var="document1"
formName="Parameter"
action="#{viewScope.noteId eq 'NEW'?'createDocument':'editDocument'}"
documentId="#{viewScope.noteId eq 'NEW'?'':viewScope.noteId}"
ignoreRequestParams="true">
</xp:dominoDocument>
</xp:this.data>
..... Dialog content ....
</xp:panel>
</xe:dialog>
When you put the data source inside the dialog, you don't refresh the page to load or prepare data sources before launching the dialog which is your current problem I guess.
Could it be that you forgot to deactivate the flag to ignore request parameters.
Sounds like the dialog is always associated with the current document instead of the parameters from the docid

xpages getDocument().getUniversalID()

I just want to test something about getting the UniversalID:
I create a computed field:
<xp:text escape="true" id="computedField3"
value="#{javascript:Cdoc.getDocument().getUniversalID()}">
</xp:text>
When I compose the doc. content which is on a Xpage, the computed field is already having some UNID and it is changing if I hit refresh. In lotus notes programming, the UNID could be get only if the current document was saved, having the default value #Text(#DocumentUniqueId).
Should I save first the Cdoc datasource to get the correct UNID? I know I'm missing something.
Thanks for your time
If you refresh your page in browser then actually a new document gets created. That's why you get a different UNID.
From your previous questions I know that you define your Cdoc as a data source with
<xp:this.data>
<xp:dominoDocument
var="Cdoc"
formName="fmPersContact">
</xp:dominoDocument>
</xp:this.data>
and that means that this Cdoc is created every time you open this XPage.
Update:
In addition, you get also a different UNID every time your field gets calculated on server when you do a partial refresh and document is not saved yet.

xpages dynamically change xpage acl?

I have a basic workflow app, and I am having diffiulty.
In the db ACL, I have all the people and groups involved set to Editor.
In an XPage acl, I am trying to enter a computed value for the name. (a field I have called nextApprover, which is stored on the form/document associated with the xpage.
I've tried
document1.getItemValue("nextApprover");
AND
getComponent("nextApprover").getValue();
both create a runtime error executing the Javascript computed expression.
All I am trying to do is allow the nextApprover the rights to edit the document when it is in their "box" and allow the rest of the users the ability to read it at that particular time. I've looked around for a while now.
Any suggestions?
You can't access the datasource document1 in XPages ACL name calculation because the ACL is first calculated and only later the datasource. That's why you get the JavaScript runtime error.
Here is an alternative to XPages ACL:
Define your datasource document1 with action="openDocument"
<xp:this.data>
<xp:dominoDocument
var="document1"
action="openDocument"
... />
</xp:this.data>
That will open the document by default in READ mode.
Then switch in beforePageLoad event to EDIT mode with context.setDocumentMode("edit") if the current user name is in your field nextApprover:
<xp:this.beforePageLoad><![CDATA[#{javascript:
if (document1.getItemValue("nextApprover").get(0).equals(session.getEffectiveUserName())) {
context.setDocumentMode("edit")
}
}]]></xp:this.beforePageLoad>
You might have to change the if clause depending on what is really in your field nextApprover.
You get better security by using Authors-items on documents instead of XPage ACL.
Try this (if document1 is datasource name):
document1.getValue("nextApprover");
If it does not work with this and you still want to use XPage ACL please post your error and XPage XML source for the ACL part.

Dynamically add custom control on Xpage

how can I add custom control on the basis of sessionScope variable. I try include page container control but no luck:
<xp:this.afterPageLoad><![CDATA[#{javascript:sessionScope.put("viewName","ccViewAll.xsp");}]]></xp:this.afterPageLoad>
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript:sessionScope.get("viewName")}]]></xp:this.value>
</xp:text>
<xc:appLayout>
<xp:this.facets>
<xp:panel xp:key="facetMiddle">
<xp:include id="include1">
<xp:this.pageName><![CDATA[${javascript:sessionScope.get("viewName")}]]>
</xp:this.pageName>
</xp:include>
</xp:panel>
</xp:this.facets>
</xc:appLayout>
The above code give me error Error 404 HTTP Web Server: Item Not Found Exception. But when I hardcode the viewname that is ccViewAll.xsp instead of sessionScope.get("viewName"), its work fine.
-MAK
You can use the dynamic content control or the switchFacet control if you have the ExtLib for XPages. The Teamroom template (demo application that comes with the ExtLib) uses these in the "allDocuments" Xpage or the "allDocsAllTab" custom control, these are good examples to look at.
If you don't have the ExtLib you could use the loaded / rendered property of a custom control to decide which one gets loaded.
e.g.
<xp:panel key="MiddleColumn">
<xc:customControl1 loaded="${javascript: if(viewScope.control == "customControl1")}"></xc:customControl1>
<xc:customControl2 loaded="${javascript: if(viewScope.control == "customControl2")}"></xc:customControl2>
</xp:panel>
loaded = false means that nothing will be done for this control.
rendered = false means that the control will be created but hidden, you can change this later to show it.
use rendered if its going to change for example when a button is clicked and loaded when its decided at start up and won't change while the user is logged in.
If you are using this to show a different view in the domino database based on some other selection that I would suggest looking at the Extension Libraries 'Dynamic View Panel' control.
Using this control means you won't need to create different custom controls for each view that you want to use, just a single page with this control and point it to the correct view to display via a scope variable.
If you need to customize how each view displays you can create a viewControl bean to set additional properties based on the view that it is showing.
Something worth to mention is that if you don't use the ExtLib - If you're using Partial Refresh then you HAVE to use the rendered property, since the loaded property only can be calculated on pageLoad.
From my understanding this means that every custom control will be computed by the server and that's probably not something you want. (Added overhead, for one thing.)
/J

Resources