on an XPage I have defined a dominoDocument datasource as followed:
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.resources>
<xp:bundle src="/datasources.properties" var="datasources" />
<xp:bundle src="/environment.properties" var="env"></xp:bundle>
</xp:this.resources>
<xp:this.data>
<xp:dominoDocument formName="fa_Attachment" var="attachDoc">
<xp:this.databaseName><![CDATA[#{javascript:return env["srv_notesname"] + "!!" + utilityBean.getFilePath() + "//" + datasources["db_inbox_filepath"]}]]></xp:this.databaseName>
</xp:dominoDocument>
</xp:this.data>
in environment.properties i have listed key/value pair:
# ENVIRONMENT SETTINGS REFERENCES
#
srv_notesname=Server01/Server/ACME
similar for datasource.properties:
# DB Inbox
db_inbox_filepath=inbox.nsf
when I load the XPage I get the message:
com.ibm.xsp.exception.EvaluationExceptionEx: Error while executing
JavaScript computed expression Error while executing JavaScript
computed expression Script interpreter error, line=1, col=8:
[ReferenceError] 'env' not found
I would have expect that I could make the data binding a bit dynamic, so what am I doing wrong?
Datasources that are children of the xp:view element need to have their properties generated before beforePageLoad. "Print" statements will allow you to confirm that, as I did for my session a few years ago "Marty, You're Just Not Thinking Fourth Dimensionally" (probably still available as a webinar on the TLCC website).
Making it a child of a Panel will allow you to pick up things set in beforePageLoad.
Datasources can't be changed during the life of a page unless scoped to request. So you can use ${javascript:...} instead of #{javascript:...}
Related
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.
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/
I'm passing a doc datasource into a Custom Control using a property defintion named docDatasource and set to a datatype com.ibm.xsp.model.domino.DominoDocumentData. Just by chance I stumbled upon an editor type named "Datasource Picker". Sounded promising, so I set it to use for m prop definition.
Upon binding the CC into my Xpage - where my doc DS is defined - I indeed can use the picker to choose my datasource ,just as I had expected. But then building the Xpage code I receive an error saying
The value of the property docDatasource cannot be primitive.
So obviously the datatype and the editor don't go along well. There's no harm done really, but I'm curious to learn what else this editor could be used for.
What to do with name of the data source passed to custom control parameter: retrieve its object by simple binding #{requestScope[compositeData.docDatasource]}.
That will return your data source and you can use this binding where needed. Or store it inside local variable and use it instead.
I dont know where you went wrong.
Here is xpage source:
<xp:this.data>
<xp:dominoDocument var="document1" formName="asdf" action="openDocument" documentId="08f6"/>
</xp:this.data>
<xc:doccc dds="#{javascript:document1}"/>
and custom control:
<xp:label id="label1">
<xp:this.value><![CDATA[#{javascript:compositeData.dds.getItemValueString("fl_name");}]]></xp:this.value>
</xp:label>
with custom control property named dds, type com.ibm.xsp.model.domino.DominoDocumentData and editor DataSourcePicker.
I used to save the current DominoDocument of the XPage in some way like:
UIViewRootEx2 view=(UIViewRootEx2) FacesContext.getCurrentInstance().getViewRoot();
DominoDocumentData ddd=(DominoDocumentData) view.getData().get(0);
DominoDocument dominoDoc=(DominoDocument) ddd.getDataObject();
//ddd.setConcurrencyMode("force");
dominoDoc.save();
To use the concurrencyMode property of the data source to avoid conflicts, I add the following line.
ddd.setConcurrencyMode("force");
I expect this behaves the same as setting the property in the XPage:
<xp:dominoDocument var="document1" formName="Test" computeWithForm="onsave" concurrencyMode="force"></xp:dominoDocument>
But it fails. It always uses the value set in the XPage source and ignores the value set in the code. Anybody knows the reason? Thanks.
I would say: works as designed. During one of the jsf phases the design is read and the value overwritten.
In JSF and thus XPages you don't mess from "Controller Code" (the stuff in your button) with the "View rendering" (your XPages source). You rather bind the property to your model (a scope variable is a good candidate) and let the runtime run its course.
So your code would be
<xp:dominoDocument var="document1"
formName="Test"
computeWithForm="onsave"
concurrencyMode="#{viewScope.myConcurrency}">
</xp:dominoDocument>
and
viewScope.myConcurrency = "force"
Hope that clarifies it.
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.