document is created if documentId is empty - xpages

I have a dominoDocument on my Xpage which gets a document from a database if a parameter is set (param.docId).
Unfortunately a document is created when the documentId results to empty (param.docId = ""). As Anonymous I am not allowed to create Documents. Therefore I get the yellow login screen.
<xp:dominoDocument
var="contactData" action="openDocument">
<xp:this.databaseName><![CDATA[#{javascript:var dbEntryConfig:DatabaseEntry=getDatabase()}]]></xp:this.databaseName>
<xp:this.documentId><![CDATA[#{javascript:var docId = param.docId;
if(docId != null){
contactSaveData.replaceItemValue("contactDataDocId",docId);
}else{
docId = contactSaveData.getItemValueString("contactDataDocId");
}
return docId;}]]>
</xp:this.documentId>
</xp:dominoDocument>
Is there any way to prevent creating a document?

By default all dominoDocument datasources will pull their settings from the URL parameters. If you're setting the documentId, you need to set ignoreRequestParams="true", otherwise anything in the URL will override whatever you define there. Also, that will ensure action="openDocument" cannot be overridden by amending the URL.
Check any save button on the page as well. If it has save="true", that means "save all datasources". Without ignoreRequestParams="true", it may also be saving this datasource. The "Save Data Sources" simple action also saves all datasources on the page.

Related

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 should I use ignorerequestParams set to true

based on these questions:
xpages UNID of documents / why it is changing
xpages why my field value isn't copied correctly
i noticed, unfortunately, some computed field which stores the UNID is changing if I hit refresh / F5.
my XPage has defined one datasource ( Cdoc ) and it contains a button which shows a dialog. this dialog has defined other datasource ( Pdoc ). The dialog contains several fields, which inherit some values from Cdoc...
Should I use ignorerequestParams property for one of these datasources? Can you explain the meaning of this property?
What happens:
The field which stores the UNID of the Cdoc after I show the dialog and create some Pdoc and list it in a viewPanel inside the XPage ( Cdoc datasource ) and then hit F5 the Cdoc UNID is changing ... even if it is computed.
Also, if the doc. isNewNote() the url is something like this:
server/Test.nsf/doc.xsp?action=newDocument
even after I call Cdoc.save(). I think this could be a reason why the computedField which stores the UNID is changing when I hit refresh => a newDoc is created.
Meanwhile, I put the ignoreRequestParams set to true just for the dialog ( Pdoc ).
Thanks for your time!
By default, the UNID and action (open, create, edit) are defined by the URL query string, i.e. the request parameters. With requestParamPrefix you can define which entry in the query string is used to find the document parameters for this datasource. By default that's documentId. But if you want to manage the UNID and action yourself through code, that's when you need to set ignoreRequestParams="true".
If you have two datasources on a page, you will need to use either ignoreRequestParams or requestParamPrefix on one of them. If not, you're editing the same document in both datasources.

Get list of all ids in an xPage container control

I am using this code to copy some documents by a button click source. I would like to prevent the end user from having to select columns and would prefer simply get all the documents ids from the view panel. Not exactly sure how to do that, or if a dataview might be a better choice for me.
var viewPanel=getComponent("viewPanel1"); //get the componet of viewPanel
var docIDArray=viewPanel.getSelectedIds(); //get the array of document ids
for(i=0;i < docIDArray.length;i++){
var docId=docIDArray[i];
var doc=database.getDocumentByID(docId);
var db=session.getCurrentDatabase();
var newDoc:NotesDocument=doc.copyToDatabase(db);
newDoc.replaceItemValue("approved","No");
var id=newDoc.getUniversalID();
newDoc.save(true);
}
Leave the view panel out of the equation: a view panel is a component, and components are for users to interact with; if the user's interaction with the view panel (i.e. "selecting" documents) doesn't alter which documents you wish to duplicate, ignore the view panel (at least, for the purposes of this specific event).
If you simply want to duplicate all documents that display in the view to which the view panel is bound, talk to the same data source the view panel is associated with. So, assuming your data source declaration looks something like the following:
<xp:panel>
<xp:this.data>
<xp:dominoView var="allDocuments" viewName="($All)" />
</xp:this.data>
<xp:viewPanel value="#{allDocuments}">
...
...then just iterate through that same view:
allDocuments.setAutoUpdate(false);
var eachDoc = allDocuments.getFirstDocument();
while(eachDoc) {
var newDoc = eachDoc.copyToDatabase(database);
newDoc.replaceItemValue("approved", "No");
newDoc.save();
newDoc.recycle();
var nextDoc = allDocuments.getNextDocument(eachDoc);
eachDoc.recycle();
eachDoc = nextDoc;
}
allDocuments.setAutoUpdate(true);
Since you're duplicating the documents within the same database, when the event finishes, the view panel will simply show twice as many documents, since you duplicated all of them. Unless, of course, the item value you're replacing disqualifies them from the view you're displaying.
NOTE 1: The reason the code above toggles the autoUpdate property is because, unless you toggle that to false prior to the iteration, when you duplicate each document, if the new document does display in the view you're iterating, the indexer will become aware of it, and you might end up in an infinite loop, because each time you try to get the next document, it's actually returning a handle on the duplicate you just created... so you would essentially be infinitely duplicating the same document until some exception is thrown (i.e. stack overflow, out of memory, etc.). Disabling autoUpdate prevents that by only allowing iteration of entries the index was aware of when your routine began.
NOTE 2: If the data source is only defined inside the view panel, move it to a parent (panel, Custom Control, or XPage) that also contains whatever component will trigger the duplication (i.e. button, link) and reference the data source within the view panel. That way both the view panel and the button can talk to the same data; otherwise, only the view panel is aware that the data source exists.

xPages - adding a field down the track

I want to add a field to an existing xPage, and need to run past a few xPage fundamentals to check their validity.
I have done the following:
In order to ensure that my dev and prod sites work, the form the document is bound to is calculated (as the datasource resides in a diff db).
My new field is called 'NewField', and I have used simple data binding, chosen document1 (same as the rest of the fields on my document), and entered the new field name (can't select from the drop down as the document is calculated).
I have also created the field on the actual notes document, however I did not think I HAD to do this? Also, it's on a calculated subform so not sure if this is relevant? This is an xpage version of an existing notes form - both client and web access are applicable for the application.
I thought it would create the field specified in 'Bind To' if it was missing, however even with it on the notes form, it still does not store the value.
Whats gone wrong:
The field is created on the document, however the value is not being populated. The value stored against the notes document is an empty string.
There is nothing complicated here, not doing anything funky, yet the value is not mapped?
The rest of the fields (created when I created the initial document) are mapped correctly.
Any suggestions? Is this a rookie error with adding fields to an existing xPage?
A
As requested, here is the code for both the data binding and a field that does work, and one that does not.
Here is my initial code to define document1. It does call an agent post save, however this agent does nothing with the field value that is not being assigned.
<xp:this.data>
<xp:dominoDocument var="document1" action="openDocument">
<xp:this.databaseName><![CDATA[#{javascript:var sname = ("","test\\testdb.nsf");
return sname;}]]>
</xp:this.databaseName>
<xp:this.formName><![CDATA[#{javascript:return "MainForm"}]]>
</xp:this.formName>
<xp:this.postSaveDocument>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:var sname = #Name([CN]",#Subset(#DbName(),1));
var dbname = "test/testdb.nsf";
var dbTest:NotesDatabase = session.getDatabase(sname, dbname);
if (dbTest.isOpen()){
ag = dbTest.getAgent("UpdateDoc");
noteid = document1.getDocument().getNoteID();
ag.run(noteid);
} }]]></xp:this.script>
</xp:executeScript>
</xp:this.postSaveDocument></xp:dominoDocument>
</xp:this.data>
And then here is the code for the field assignment that is not working.
<xp:inputText value="#{document1.NewField}"
id="inputText25" disableClientSideValidation="true" styleClass="entryboxes">
</xp:inputText>
And then here is the code for a field assignment that is working.
<xp:inputText value="#{document1.CLRef}"
id="inputText4" rendered="#{javascript:#IsNewDoc()}" styleClass="entryboxes">
</xp:inputText>
I thought that this was fairly standard.
update 8/10
So - I have worked out that this happens only when I have conditionally hidden cell. This has a basic formula, asking the row to be visible based on the value of another field. The display / no display functionality is working (see below for code), yet, for a reason unknown to me, it does not save the value.
var hw = getComponent("module");
var hwv = hw2.getSubmittedValue();
hwv == "Product1" || hwv == "Product2" || hw2v == "Product3"
If I create any other field NOT hidden (and make up the field name), it maps to the document correctly (as I thought it should). The good news is I have managed to replicate with a new form, so it appears to be with me wanting to hide a row conditionally, and not an issue with my form? Any ideas?
OK - I continued to have issues with the field mapping when the cell was hidden in certain conditions. So, I ended up making the cell visible, and then having the field mandatory only in certain circumstances. So, question not answers, but a work around used.

Xpages- Create New copy of saved document and open it without saving it

I have a document that I want to create a new version/copy of, so I am trying to do server-side javascript to
Create a new document
copy all items from the current document
open the new document that I have created, without saving it
I am not able to open the newly created document, is this possible?
code I am using is:
var viewPanel=getComponent("viewPanel1");get the componet of viewPanel
var docIDArray=viewPanel.getSelectedIds(); get the array of document ids
for(i=0;i < docIDArray.length; i++){
var docId=docIDArray[i];
var doc=database.getDocumentByID(docId);
var newDoc = database.CreateDocument
doc.CopyAllItems (newDoc)
var docUNID = newDoc.getUniversalID ()
// need something here to open copied document
}
You need to store the IDs in the session scope and then open the page and do the copy inside in one of the data source events:
var viewPanel=getComponent("viewPanel1");get the componet of viewPanel
var docIDArray=viewPanel.getSelectedIds(); get the array of document ids
sessionScope.alltheDocs = docIDArray;
then open the page where you want to have the new document. Inside that page you need to have a repeat control that matches the element count of alltheDocs. I probably would design it using a DojoTab container (one tab per document). Inside the repeat place a panel with a data source (or a custom control). Then in the queryNewDocument event you copy the fields using the variable name of your datasource.
You could save these docs, then show them and add them to a deletion queue by marking a field on those docs. On save remove them from deletion queue as a work around possibly.
1) Do not store Notes object to scope lasting longer than request.
2) If XPage has to inherit some values, it needs to read them from some source.
3) You can not inherit data from Notes document - according to (1) in memory object must not be stored in sessionScope (simplest way to pass objects between two pages), and you can not retrieve it by UNID/key (it is not saved, as requested).
So, (possibly) the only option is:
Make copy of source document - copy every field you are interested in into Map[String,Object]. Fields must be converted into "raw" objects String, Double, Date (java, not Notes) or their vectors for multivalues. You must not copy special (Notes objects) fields - names, dates, rich text! Names can be converted to strings, Dates can be retrieved as Java dates, rich text might be treated as MIME (String) (but with possible loss of formatting). I think you don't want to pass attachments.
In target XPage, define queryNewDocument event to lookup and initialize fields from this Map object. Delete the sessionScope object to prevent duplicates.
I needed very similar thing in my application. I have XPage with a source document opened in read mode. There is a button that creates a new document and set few values (using the source document). I wanted the XPage to open this new document in Edit mode after it was created.
Note: I could not use redirect with URL parametr action as I needed to open it in a same XPage and preserve a view scope variables and beans.
Solution:
Add View Scope variables NewDocAction and documentId (on button click),
Partial refresh of XPage (on button)
Compute document data source using viewScope variable documentId
Check presence of View Scope variable NewDocAction (in onClienLoad event)
javascript code in the button:
var travelDoc = xpBean.createTravelDoc(requestDoc);
if (travelDoc != null){
viewScope.put("content","travelForm"); //to render proper CC on XPage
viewScope.put("documentId", travelDoc.getUniversalID());
viewScope.put("NewDocAction", "ToEditMode");
}
javascript code in a onClientLoad event of a travelForm custom control:
if (viewScope.containsKey("NewDocAction") && viewScope.get("NewDocAction").equals("ToEditMode")){
context.setDocumentMode("travelDoc","edit");
viewScope.remove("NewDocAction");
}

Resources