XPages - onchange event on inputtext field lose click - xpages

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?

Related

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 message box before logging out

I have the following code logging out the user from app and "send" him back to the session based authentication page ( Thanks Paul Withers ):
clearing_function(sessionScope);
var appUrl = facesContext.getExternalContext().getRequest().getContextPath();
var url = appUrl + "?logout&redirectto=" + appUrl;
facesContext.getExternalContext().redirect(url);
Is there any chance to have like a #prompt formula with yes/no and just in case if user selects yes the above code ( from ssjs ) to be executed? Or I must write the confirmation message in csjs. But, then, how can I transform the above code in csjs?
You can use the Dialog component from extension library to build a confirmation box with two buttons where the positive button runs your logout code
<xe:dialog id="dialog1">
<xp:panel>
<xp:button value="OK" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:clearing_function(sessionScope);
var appUrl = facesContext.getExternalContext().getRequest().getContextPath();
var url = appUrl + "?logout&redirectto=" + appUrl;
facesContext.getExternalContext().redirect(url);}]]></xp:this.action>
</xp:eventHandler></xp:button>
<xp:button value="Cancel" id="button2">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="dialog1">
<xp:this.action><![CDATA[#{javascript:getComponent("dialog1").hide();}]]> </xp:this.action>
</xp:eventHandler></xp:button></xp:panel>
</xe:dialog>
To hide the default x button just override the relevant css classes:
for oneui themes it's the "lotusBtnImg" class
for webstandard it's the ".dijitDialogCloseIcon" class

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

XPages save data source and new doc changes previous doc

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>

Resources