XPages save data source and new doc changes previous doc - xpages

I have a document data source (create document with no parent id) bound to a panel. Within the panel I have 2 other panels. On completing the fields in panel 1 I click a link to reveal the 2nd panel and that has a save button on it. Once saved the document appears in the db correctly.
The save buttons does a dds save and then clears all fields and does a partial update on the outer panel and a partial execute on that panel too as I have other dds on the XPage outside of my main panel.
If I now create another document the previous document gets updated rather than create a new doc. I've tried different scope for the dds and other options. Not sure what to try next.
Anyone know what the problem is?

Here is a example how you can add a new datasource with a partial refresh:
<xp:panel id="myPanel">
<xp:this.data>
<xp:dominoDocument var="document1"></xp:dominoDocument>
</xp:this.data>
<xp:br></xp:br>
<xp:inputText id="inputText1" value="#{document1.Test}"></xp:inputText>
<xp:br></xp:br>
<xp:br></xp:br>
<xp:button value="Save" id="buttonSave">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="myPanel">
<xp:this.action>
<xp:actionGroup>
<xp:saveDocument var="document1"></xp:saveDocument>
<xp:executeScript>
<xp:this.script>
<![CDATA[#{javascript:
var panel = getComponent("myPanel");
var ds = new com.ibm.xsp.model.domino.DominoDocumentData();
ds.setComponent(panel);
ds.setVar("document1");
panel.getData().clear();
panel.addData(ds);
}]]>
</xp:this.script>
</xp:executeScript>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
Hope this helps
Sven
EDIT:
Added a clear() to remove all previous defined datasources from the panel.

That's default behaviour. If you don't want to reload the whole page one option is to get rid of the datasource and create the new doc in SSJS event when Save button is clicked.

I used Sven's answer succesfully, however, I had to add an extra line in ths server side JavaScript
<xp:executeScript>
<xp:this.script>
<![CDATA[#{javascript:
var panel = getComponent("myPanel");
var ds = new com.ibm.xsp.model.domino.DominoDocumentData();
ds.setComponent(panel);
ds.setVar("document1");
ds.setFormName('form1');
panel.getData().clear();
panel.addData(ds);
}]]>
</xp:this.script>
</xp:executeScript>

Related

How to sync edit mode with responses in xp:repeat

Notes-wise, I have a main doc and its responses documents.
XPage-wise, main doc and responses are displayed in the same xp:view, the responses being in a xp:table constructed by a xp:repeat
Each row of the table holds a panel, whose datasource is of course bound to the particular response.
So far, pretty straightforward, isn't it ?
I would like very much to ensure that, at any time, the edit mode of the main doc and the responses are in sync. Something along the lines of :
Everything is in read-only mode
User switches main doc to edit mode, automagically all responses switch to edit mode too
Ditto in reverse : switching main doc to read-only switches responses to read-only
I tried to dynamically compute the "action" attributes of the data sources in the rows, but that does not seem to work.
I'm thinking of somehow having the responses listen to the event "main doc changes mode" and acting accordingly, but I can't seem to be able to wrap my head around how to do it. Specifically, which event would that be ? Then, how to have the responses listen to an event happening somewhere else ?
Any hint appreciated
thx
edit : back a few days later, if anyone still there.
As per stwissel's suggestion, here be code :
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex"
style="background-color:rgb(217,217,255)">
<xp:this.data>
<xp:dominoView
var="subdocsNotesView"
viewName="#{javascript:compositeData.subdocsNotesView}"
categoryFilter="#{javascript:compositeData.ctnrK}">
</xp:dominoView>
</xp:this.data>
<xp:table>
<xp:repeat
id="leRepeat"
value="#{subdocsNotesView}"
var="oneDoc">
<xp:tr>
<xp:panel id="rowPanel">
<xp:this.data>
<xp:dominoDocument
var="rowData"
formName="Person"
documentId="#{javascript:oneDoc.getDocument().getUniversalID()}"
action="editDocument">
</xp:dominoDocument>
</xp:this.data>
<xp:td>
<xp:inputText
id="Name"
value="#{rowData.Name}"
defaultValue="#{javascript:oneDoc.getDocument().getItemValueString('Name')}">
</xp:inputText>
</xp:td>
</xp:panel>
</xp:tr>
</xp:repeat>
</xp:table>
</xp:view>
Surround your repeat control with a panel.
Calculate panel's property readonly depending on main document's read or edit mode.
Use a boolean viewScope variable "editMode" to memorize the current mode.
<xp:table>
<xp:panel readonly="#{ not viewScope.editMode}">
<xp:repeat ...>
...
</xp:repeat>
</xp:panel>
</xp:table>
Change mode in buttons:
<xp:button value="Editmode" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:actionGroup>
<xp:changeDocumentMode mode="edit" var="mainDocument">
</xp:changeDocumentMode>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:
viewScope.editMode = true
}]]></xp:this.script>
</xp:executeScript>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button value="Readmode" id="button2">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:actionGroup>
<xp:changeDocumentMode mode="readOnly" var="mainDocument">
</xp:changeDocumentMode>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:
viewScope.editMode = false
}]]></xp:this.script>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
Even though repeat's dominoDocument has always property action="editDocument" repeat documents are in read mode when panel's property readonly is true.
If panel's property readonly is false then repeat documents are in edit mode.
This way edit mode of main document and repeat documents is in sync.
I would recommend using a Managed Bean which implements the Model View Controller (MVC). The Controller Bean in the view scope contains the current Main Doc model and coordinates access to the main doc and its responses. The Main Doc Model would include an array of the Response Doc Model so that the read mode is managed at the Controller while the data is managed in the model.
John Dalsgaard has an excellent presentation on this topic located here.
I use this approach for both Parent/Child documents and for documents that contain items which are related or synced lists.
Happy coding.

My dialog control does not update my xpage

I try to update items via a dialog control.
But my control OK button (or any other function in the dialog) do not refresh my "underlying" xpage.
I^m sure it's sth quite simple ....
the (symplified example) code of the dialog:
<xe:dialog id="diaSnippet" title="Update my xpage" extractContent="true"
preload="true">
<xe:dialogContent id="dialogContent1">
<xp:panel>
<xp:inputText value="#{test.dialog1}" id="inputText1">
<xp:this.defaultValue><![CDATA[#{javascript:test.getItemValueString("item1")}]]></xp:this.defaultValue>
</xp:inputText>
</xp:panel>
</xe:dialogContent>
<xe:dialogButtonBar id="dialogButtonBar1">
<xp:panel>
<xp:button id="button3" value="OK">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:test.replaceItemValue("item1","1234")
getComponent("diaSnippet").hide()}]]></xp:this.action>
</xp:eventHandler></xp:button>
</xp:panel>
</xe:dialogButtonBar>
</xe:dialog>
in my understanding the Ok should update the xpage, and should change the value of the item "item1", but it does nothing.
thx in advance for any help, Uwe
argh .... now I found the answer in the wiki:
http://www-10.lotus.com/ldd/ddwiki.nsf/xpDocViewer.xsp?lookupName=Domino+Designer+XPages+Extension+Library#action=openDocument&res_title=Modal_dialogs_ddxl853&content=pdcontent
The settings in the "Server Options" on the event tab seem to do nothing, but writing the ID(s) to be refreshed in the hide() method does the trick.
So instead of getComponent("diaSnippet").hide() I write getComponent("diaSnippet").hide("IDtorefresh)
Uwe

XPages - onchange event on inputtext field lose click

I have a simple form with an onchange event on a field of type inputText.
Onchange event start when I click another object. Example the save button.
The code runs but the onchange click on the Save button is lost.
I enclose the sample code of a page that reproduces the problem.
Suggestions?
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:div style="padding:20px;"></xp:div>
<xp:button value="Save" id="button1" style="margin:20px;">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:print('click');}]]></xp:this.action>
<xp:this.script><![CDATA[alert('click');]]></xp:this.script>
</xp:eventHandler>
</xp:button>
<xp:radioGroup id="radioGroup1" style="margin:20px;">
<xp:selectItem itemLabel="val1"></xp:selectItem>
<xp:selectItem itemLabel="val2"></xp:selectItem>
<xp:selectItem itemLabel="val3"></xp:selectItem>
<xp:eventHandler event="onchange" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:print('onchange - radiobutton');}]]></xp:this.action>
</xp:eventHandler>
</xp:radioGroup>
<xp:inputText id="inputText1" style="margin:20px;">
<xp:eventHandler event="onchange" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:print('onchange - start');
var millis = 10000;
var date = new Date();
var curDate = null;
do { curDate = new Date(); }
while(curDate-date < millis);
print('onchange - finish');}]]></xp:this.action>
</xp:eventHandler>
</xp:inputText>
</xp:view>
You can do it by oninput event instead of onchange. Just change the event attribute in the eventHandler. However,
It's not supported before IE9,
Every keystroke will trigger the event which could be bad for user-experience
In case of a partial refresh, when the refresh is over, the focus will be shifted to another component if it's not the first item in the form. Again, bad for UX.
You may also fire a CSJS code on onkeyup event to focus another component on the page. Therefore it will refresh the page. You may do this with setTimeout() function therefore, if the user does not press any keys for a moment, it will fire the refresh.
Thanks for reply but I think that these solutions are not good for UX.
I think that only possible solutions are:
1 disable server onchange event and add refresh button
2 when possible use onchange client js event
Others suggestion?

No luck while opening a link in new tab using XPages

I am working on application and I got stuck when I wanted to open a link on new tab or window.
I am using Lotus Notes Designer Release 8.5.2FP1.
I have attached my piece of code.
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:try{
var doc = database.getProfileDocument("frmConfiguration","");
var url = doc.getItemValueString("HeaderLink1URL");
view.postScript("var tempwindow =window.open('" +url+"','_blank');tempwindow.focus();");
}catch(e){
}}]]></xp:this.action>
Based on your updated code in comment you can simply add target="_blank" and instead of using the onClick event use the value attribute which would point to the URL to be opened. So your code would be something like this:
<xp:link escape="false" id="link1" target="_blank">
<xp:this.text>some code</xp:this.text>
<xp:this.value><![CDATA[#{javascript:var doc = database.getProfileDocument("frmConfiguration","");
var href = doc.getItemValueString("HeaderLink1URL");
return href;}]]></xp:this.value>
</xp:link>
The simpliest way to do this would be something like:
<xp:text escape="false" id="newTab"><xp:this.value><![CDATA[#{javascript:return "Google";}]]></xp:this.value></xp:text>
This will open google in a addtional tab.
Update:
If you want to use a xp:link you could try:
<xp:link escape="false" id="newTab" text="test">
<xp:this.onclick><![CDATA[var ret = window.open("http://www.google.com",'_blank');
]]></xp:this.onclick>
</xp:link>
If you want to open the link in a seperate window or tab i recomend dont use the aktion use the onclick client side event in the option tab.
Here is some sample code of opening a URL both client side and server side.
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:button value="Client Side Open Button." id="ClientSideButton">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[var href = "http://www.ibm.com";
var tempwindow = window.open(href,'_blank');
tempwindow.focus();
]]></xp:this.script>
</xp:eventHandler>
</xp:button>
<xp:br></xp:br>
<xp:br></xp:br>
<xp:button id="serverSideButton" value="Server Side Open Button ">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:var href = "http://www.ibm.com";
view.postScript("var tempwindow = window.open('" + href + "','_blank'); tempwindow.focus();");
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:view>
If this code does not work as expected, two things to check.
Check that the url variable is being set correctly.
Make sure you are on the latest release. window.open() didn't work as expected until 8.5.1FP2.

Partial refresh on dynamic field binding removes values

Really looking for an idea why my XPage is doing this.
I have field with a dynamic databinding:
<xp:inputText id="CORE_Input" value="#{Document[compositeData.PARA_DataBinding]}"</xp:inputText>
That works quit well until I start to hide it based on a notes formula.
Let me tell what it does: I click a checkbox in my XPage. That checkbox is running SSJS which is calling: Document.getDocument(true) to push the data from my XPage back into the notesdocument without saving it. Once that is done I can use session.evaluate("checkbox!="something"") to hide the inputText field.
It works quit well but the problem is that once I untick the checkbox the value is gone from the inputfield.
If you know a better way to use notes formulas for hiding or the reason why the inputfield is empty once it comes back would be highly appreciated. Here is an example:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:checkBox id="checkBox1" value="#{Document.Check}" text="hide" checkedValue="hide">
<xp:eventHandler event="onchange" submit="false">
<xp:this.script><![CDATA[document.getElementById("#{id:hide}").click()]]></xp:this.script>
</xp:eventHandler>
</xp:checkBox>
<xp:panel id="test">
<xp:inputText id="CORE_Input" type="#{compositeData.NODE}"
value="#{Document[compositeData.PARA_DataBinding]}"
defaultValue="#{javascript:compositeData.PARA_DefaultValue}" style="margin-left:24px">
<xp:this.styleClass><![CDATA[#{javascript:DOMElement.getAttribute("stylesize");}]]></xp:this.styleClass> <xp:this.rendered><![CDATA[#{javascript:var doc:NotesXspDocument=Document;
var erg=session.evaluate('Check="hide"',doc.getDocument());
if(#Text(erg)=="1")
{return false}
else
{return true}}]]></xp:this.rendered>
</xp:inputText>
<xp:button value="hide" id="hide">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="test">
<xp:this.action>
<![CDATA[#{javascript:var doc:NotesXspDocument=Document;doc.getDocument(true)}]]></xp:this.action>
</xp:eventHandler></xp:button>
<xp:button value="unhide" id="unhide">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="test">
<xp:this.action><![CDATA[#{javascript:sessionScope.hide=""}]]></xp:this.action>
</xp:eventHandler></xp:button>
</xp:panel></xp:view>
The problem you have is your default value: As soon the component is unhidden, the value is recalculated. You have to check if the component is partially refreshed. If so, stop the recalculation:
<xp:this.defaultValue>
<![CDATA[#{javascript:
importPackage( com.ibm.xsp.ajax );
if( AjaxUtil.isAjaxPartialRefresh(facesContext) == true )
return;
compositeData.PARA_DefaultValue
}]]>
</xp:this.defaultValue>
This should solve your problem

Resources