Partial refresh on dynamic field binding removes values - xpages

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

Related

How to do a partial refresh of multiple items in Xpages correctly

I have read many of the blog posts on doing a partial refresh on more than one element, but I cannot seem to get it to work.
I made a "toy" example, an Xpage with two fields and one button. Both fields are bound to a sessionScope counter. The button increments the counter and does a partial refresh on the containing panel.
I want to do a partial refresh on the first field, which is not in the panel [in my real Xpage the two fields are very far apart on the form.
Tried many different things to get this to work, but none worked. Is it even possible to do this?
<?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"
xmlns:xc="http://www.ibm.com/xsp/custom"
style="background-position:center left"
xmlns:on="http://www.openntf.org/domino/xsp" viewState="nostate"
xmlns:debug="http://www.openntf.org/xsp/debugtoolbar">
First Var<br></br>
<xp:text escape="true" id="computedField1" value="#{sessionScope.number}">
</xp:text>
<br></br>
<xp:br></xp:br>
<br></br>
Second Var<xp:panel id="pnl1">
<xp:text escape="true" id="computedField2" value="#{sessionScope.number}">
</xp:text>
<br></br>
<br></br>
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="pnl1" execMode="partial"
execId="pnl1">
<xp:this.action><![CDATA[#{javascript:var t = sessionScope.number + 1;
sessionScope.number = t;}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:view>
Read Knut's link and got this to work. I made a change to the event handler of the button and it worked. Here is the code:
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="pnl1" execMode="partial"
execId="pnl1">
<xp:this.action><![CDATA[#{javascript:var t = sessionScope.number + 1;
sessionScope.number = t;}]]></xp:this.action>
<xp:this.onComplete><![CDATA[XSP.partialRefreshPost("#{id:computedField1}");]]></xp:this.onComplete>
</xp:eventHandler>
Use XSP.partialRefreshPost(): http://avatar.red-pill.mobi/tim/blog.nsf/d6plinks/TTRY-84B6VP

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?

xpages - prevent SSJS on page load in CSJS

I have some SSJS within CSJS onclick event of a button. Is there any way to prevent this SSJS from executing during page load?
Thanks
This can be done by checking facesContext.getRenderResponse(). If it is true, the page is reloaded, otherwise it is false. The flag is not set correctly but gives you an easy way to check if the page is loaded or not.
Here is an example XPage:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:button value="Reload CSJS" id="buttonReloadCSJS">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.script>
<![CDATA[#{javascript:
facesContext.getRenderResponse()?"alert('NotOnLoad');":"alert('OnLoad')";
}]]>
</xp:this.script>
</xp:eventHandler>
</xp:button>
</xp:view>
If you open the XPage and click the button, the page will be reloaded and you will have another CSJS code.
EDIT:
Here is another way to calculate code only if the button was partial refreshed:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:div id="refreshMe">
<xp:button value="Reload CSJS" id="buttonReloadCSJS">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="refreshMe">
<xp:this.script>
<![CDATA[#{javascript:
var ajax = new com.ibm.xsp.ajax.AjaxUtil();
if( ajax.isAjaxPartialRefresh(facesContext) == true){
return "alert('Refreshed')";
}
}]]>
</xp:this.script>
</xp:eventHandler>
</xp:button>
</xp:div>
</xp:view>

When I save a document from an extension library dialog box some values are blank

Using 8.5.3 UP1
When I save my document from a dialog box certain fields are not being populated. If I save the document from within the xpage it saves these fields just fine. Here is a simple example to illustrate the issue:
<xp:link text="Save Document By Dialog"
id="link21">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[XSP.openDialog("#{id:dialog1}");]]></xp:this.script>
</xp:eventHandler>
</xp:link>
<br/>
<xp:button value="Save By Button" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:saveDocument var="document1"></xp:saveDocument>
</xp:this.action>
</xp:eventHandler>
</xp:button>
<xe:dialog id="dialog1" title="Dialog">
<br />
<b>
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript:"Save this document?"}]]></xp:this.value>
</xp:text>
</b>
<br />
<br />
<xp:button value="Yes" id="button7">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.script><![CDATA[XSP.closeDialog("#{id:dialog1}");]]></xp:this.script>
<xp:this.action>
<xp:saveDocument var="document1"></xp:saveDocument>
</xp:this.action></xp:eventHandler>
</xp:button>
<xp:button value="No" id="button8">
<xp:this.onclick><![CDATA[XSP.closeDialog("#{id:dialog1}");]]></xp:this.onclick>
</xp:button>
</xe:dialog>
<br/><br/>
<xp:inputText id="TitleTX" value="#{document1.TitleTX}"></xp:inputText>
<br/><br/>
<xp:inputRichText id="inputRichText1" value="#{document1.ProcessMapsRT}">
</xp:inputRichText>
The DOJO processes associated with the xe:dialog moves the dialog to another place in the DOM which means it will loose track of the data sources in the main parts of the document. If you do you saving in the dialog with SSJS instead of simple actions it may work better.
I have had the most success using a dialog contained in a custom control where the datasource is passed in through the composite data. That way the connection to the data is not lost and still works, BUT, I still use SSJS for saving in these situations.
/Newbs
UPDATE: This may be a time to use the technique Steve Pridemore described in NotesIn9 #42 (see xpages.tv).
First put a new event onto your XPage at the level with the data source in it.
<xp:eventHandler
id="saveEventHandler"
submit="true"
save="true"
event="calledbyid"
refreshMode="complete">
</xp:eventHandler>
Next, have the action in the dialog invoke this event using client side javascript:
XSP.executeOnServer('#{id:saveEventHandler}')
That "should" do it. I have not fully tested it but the examples from NoteIn9 do work.
/Newbs
Have you tried using dataContexts to define your datasource? I believe dataContext is a global object.
Update: dataContexts or even dominoDocument datasource worked when saving a document, but the problem was that the values were not saved. I therefore used a viewScope variable to store the values and that did the trick. I am not sure if this will help you, but here you go, this works for me:
<?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:this.data>
<xp:dominoDocument var="newDoc" formName="frmContact"></xp:dominoDocument>
</xp:this.data>
<xp:inputText id="inputText1" value="#{viewScope.firstName}"></xp:inputText>
<xp:inputText id="inputText2" value="#{viewScope.lastName}"></xp:inputText>
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="dialog1">
<xp:this.action><![CDATA[#{javascript:getComponent("dialog1").show();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xe:dialog id="dialog1">
<xp:button value="Label" id="button2">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:newDoc.replaceItemValue("fldFirstName", viewScope.firstName);
newDoc.replaceItemValue("fldLastName", viewScope.lastName);
newDoc.save();
getComponent("dialog1").hide();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xe:dialog>
</xp:view>
Hope this helps!
Ensure your data are posted to server before opening dialog. I would suggest to open such dialog with SSJS syntax - getComponent("dialog1").show()

Resources