how to define a conditional xp:confirm? - xpages

I would like to use the xp:confirm action on a conditional status. Is there a way to compute the rendered property of this control?
I can compute the rendered property for the whole xp:eventHandler but not for an xp:actionGroup or xp:confirm.

xp:confirm just adds client-side JavaScript to the button with:
if (!XSP.confirm("YOUR MESSAGE")){
return false;
}
XSP.confirm() is an XPages wrapper for JavaScript confirm. The most flexible approach is to code the client-side JavaScript you want on the "Client" tab of the button, doing return false to prevent the button sending to the server as required.

This is a very synthetic snippet which you however can fit to your needs, if I got you right and if it suits your use case. Not so elegant, but works.
<xp:panel id="mainPanel">
<xp:button id="myBtn1"
value="Ask confirmation on submit">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="mainPanel">
<xp:this.action>
#{javascript:
requestScope.put('myAnyVar', 'askConfirmation');
}
</xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button id="myBtn2"
value="Dont ask confirmation on submit">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="mainPanel">
<xp:this.action>
#{javascript:
requestScope.put('myAnyVar','dontAskConfirmation');
}
</xp:this.action>
</xp:eventHandler>
</xp:button>
<input type="hidden" id="doConfirm"
value="#{requestScope.myAnyVar eq 'askConfirmation' ? '1' : '0'}">
</input>
</xp:panel>
<br />
<br />
<xp:button id="btnSubmit"
value="Submit">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.script>
var confirmOption = dojo.byId('doConfirm').value;
if (confirmOption === '1') {
if (confirm('Proceed the submit?')) {
return true;
} else {
return false;
}
} else {
return true;
}
</xp:this.script>
<xp:this.action>
#{javascript:
viewScope.smthSubmitted = new java.util.Date();
}
</xp:this.action>
</xp:eventHandler>
</xp:button>
<br />
<br />
<xp:text value="Submit time: #{viewScope.smthSubmitted}" />

Related

checkbox control not calculating value consistently

I want to use the feature of the checkbox control by using SSJS to return "true" or "false" based on the value of a session variable. The calculation only runs when the page is completely refreshed. The code does not on a partial or full refresh once the page is loaded (The only exception is that the code will run on the first partial or full refresh - which is interesting). I wrote a quick demonstration program.
I am sure this has something to do with the JSF lifecycle, but am not sophisticated in the technology to decipher what is going on.
Thanks,
---Lisa&
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.beforeRenderResponse><![CDATA[#{javascript:if (sessionScope.uncheck === true) {
sessionScope.checked = false;
} else {
sessionScope.checked = true;
}}]]></xp:this.beforeRenderResponse>
<xp:panel id="Panel1">
<xp:label id="label1" value="Panel1" style="font-weight:bold"></xp:label>
<xp:button id="button1" value="Button1 - Check the Box">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="Panel2">
<xp:this.action><![CDATA[#{javascript:sessionScope.checked = true;
print("just clicked Button1 sessionScope.checked = ",sessionScope.checked);}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button id="button3" value="Button 2 - Uncheck the Box">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="Panel2">
<xp:this.action><![CDATA[#{javascript:sessionScope.checked = false;
print("just clicked Button2 sessionScope.checked = ",sessionScope.checked);}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button id="button2" value="Reload page - Uncheck the Box">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:sessionScope.uncheck = true;
context.reloadPage();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button id="button4" value="Reload page - Check the Box">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:sessionScope.uncheck = false;
context.reloadPage();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
<xp:panel id="Panel2">
<xp:label id="label2" value="Panel2" style="font-weight:bold">
</xp:label>
<xp:checkBox id="checkBox1" text="Computed Checkbox">
<xp:this.defaultChecked><![CDATA[#{javascript:print("Calculating CheckBox - sessionScope.checked = ",sessionScope.checked);
return sessionScope.checked}]]></xp:this.defaultChecked>
</xp:checkBox>
</xp:panel>
</xp:view>
Bind your sessionScope variable directly to the xp:checkBox. This way any changes to the sessionScope variable will be reflected by the checkbox when refreshed:
<xp:checkBox id="checkBox1" text="Computed Checkbox" value="#{sessionScope.checked}"></xp:checkBox>
Here's an example using your buttons for partial refresh and for full reload:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:panel id="Panel1">
<xp:label id="label1" value="Panel1" style="font-weight:bold"></xp:label>
<xp:button id="button1" value="Button1 - Check the Box">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="Panel2">
<xp:this.action><![CDATA[#{javascript:
sessionScope.checked = true;
print("just clicked Button1 sessionScope.checked = ",sessionScope.checked);
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button id="button3" value="Button 2 - Uncheck the Box">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="Panel2">
<xp:this.action><![CDATA[#{javascript:
sessionScope.checked = false;
print("just clicked Button2 sessionScope.checked = ",sessionScope.checked);
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button id="button2" value="Reload page - Uncheck the Box">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:
sessionScope.checked = true;
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button id="button4" value="Reload page - Check the Box">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:
sessionScope.checked = false;
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
<xp:panel id="Panel2">
<xp:label id="label2" value="Panel2" style="font-weight:bold">
</xp:label>
<xp:checkBox id="checkBox1" text="Computed Checkbox" value="#{sessionScope.checked}"></xp:checkBox>
</xp:panel>
</xp:view>

put tabPanel forward: best method?

i tried this with sessionScope (didn't work):
The following Tabs should be controllable with the help of variable 'm1':
<xp:tabbedPanel id="tabbedPanel1"
selectedTab="#{javascript:sessionScope.get('m1')}">
<xp:tabPanel label="Config" id="conf">
<xc:k_conf></xc:k_conf>
</xp:tabPanel>
<xp:tabPanel label="Solution" id="sol">
<xc:k_sol></xc:k_sol>
</xp:tabPanel>
</xp:tabbedPanel>
In Control k_conf is a button 'calculate' which performs an agent and then sets the varable 'm1' to 'sol'.
I would expect, that the Tab switches to 'Solution', but nothing happens (although refreshmode="complete").
<xp:button value="calculate" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
...
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:
...
agent.runWithDocumentContext(docVG.getDocument());
sessionScope.put("m1","sol");
}]]>
</xp:this.script>
</xp:executeScript>
...
</xp:button>
Another approach was to use component (didn't work because 'show is not allowed for TabPanel'):
<xp:this.action>
<![CDATA[#{javascript:
var c = getComponent("IdofTab");
c.show("IdofTab");
}]]>
</xp:this.action>
That sessionScope approach should work, I just tried it and verified that. Is there some CSJS part to the button eventHandler that is not returning true and thus preventing the SSJS executeScript from being performed?
For the second approach, you can use the setSelectedTab method of the tabbed panel rather than show, for example:
<xp:button id="button2" value="Change Tab 4">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action>
<![CDATA[#{javascript:
var c = getComponent("tabbedPanel1");
c.setSelectedTab("tabPanel4");
}]]>
</xp:this.action>
</xp:eventHandler>
</xp:button>

Set field focus after validation in dialog (Extension Library Dialog)

I have the following dialog, the password field focus is set when the dialog has focus but this only works when first loaded, I want to set the password field focus when the passwords don't match (i.e. after clicking the OK button and running the SSJS).
<xe:dialog id="dialogConfirmPassword" title="Confirm Your Password">
<xe:dialogContent id="dialogConfirmPasswordContent">
<xp:messages id="messagesConfirmPassword" layout="table" />
<xp:table style="width:100%" id="tableConfirmPassword">
<xp:tr>
<xp:td>
<xp:label value="Password" id="lblPassword"
for="confirmPassword" />
</xp:td>
<xp:td>
<xp:inputText id="confirmPassword"
password="true">
</xp:inputText>
</xp:td>
</xp:tr>
</xp:table>
</xe:dialogContent>
<xe:dialogButtonBar id="dialogButtonBarConfirmPassword">
<xp:button value="OK" id="btnConfirmPasswordOk">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:actionGroup>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:try{
var confirmPassword:String = getComponent("confirmPassword").getValueAsString();
if (session.verifyPassword(confirmPassword, HTTPPassword)){
/* RUNS NOTES AGENT */
getComponent('dialogConfirmPassword').hide();
return true;
} else {
facesContext.addMessage("messagesConfirmPassword", new javax.faces.application.FacesMessage("You have entered an incorrect password, please try again.") );
/* WANT TO SET FOCUS FOR PASSWORD FIELD */
return false;
}
} catch (e) {
facesContext.addMessage("messagesConfirmPassword", new javax.faces.application.FacesMessage("ERROR! " + e.toString()) )
return false;
}}]]></xp:this.script>
</xp:executeScript>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
</xe:dialogButtonBar>
<xp:eventHandler event="onFocus" submit="false">
<xe:this.script><![CDATA[dijit.byId("dialogConfirmPassword").focus();]]></xe:this.script>
</xp:eventHandler>
</xe:dialog>
Can I set the password field focus after setting the facesContext.addMessage or another way?
Update: The following output script worked:
<xp:scriptBlock id="scriptBlockConfirmPassword">
<xp:this.value><![CDATA[#{javascript: if(viewScope.PWDSuccess === null) {
return "";
};
var result = "dojo.byId(\"";
result += getComponent("confirmPassword").getClientId(facesContext);
result += "\").focus();";
return result;}]]></xp:this.value>
</xp:scriptBlock>
A few pointers:
Don't go after components like getComponent("confirmPassword") but bind your component to a scope variable, makes better code
You can't directly run a Client JavaScript action in your SSJS (where you indicated)
Your event handler never works since the XPages ID is different from the clientside ID
A outputscript probably can solve your challenge
So modify your code (only essentials here):
<xp:inputText id="confirmPassword" password="true" value="#{viewScope.confirmPWD}">
</xp:inputText>
<xp:button value="OK" id="btnConfirmPasswordOk">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action>
<xp:actionGroup>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:try{
viewScope.PWDSuccess = session.verifyPassword(viewScope.confirmPWD, HTTPPassword);
if (viewScope.PWDSuccess){
/* RUNS NOTES AGENT */
getComponent('dialogConfirmPassword').hide();
} else {
facesContext.addMessage("messagesConfirmPassword", new javax.faces.application.FacesMessage("You have entered an incorrect password, please try again.") );
}
} catch (e) {
facesContext.addMessage("messagesConfirmPassword", new javax.faces.application.FacesMessage("ERROR! " + e.toString()) );
viewScope.PWDSuccess = false;
}
return viewScope.PWDSuccess
}]]></xp:this.script>
</xp:executeScript>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:outputScript>
<this.value><!CDATA[#{javascript:if(viewScope.PWDSuccess) {return "";};
var result = "dijit.byId(\"";
result += getComponent("confirmPassword").getClientId();
result += "\").focus();";
return result;
}]]</this.value>
</xp:outputScript>
(Typed off my head - will contain errors).
Let us know how it goes.

Section close/open with partial refresh

I have a section in my xpage, it's open by default. When i close the section and make a partial refresh it opens the section again.
Is there a easy way the prevent this.
Hehe, according to your problem i build a small XPage to test what i commented here is what i got:
<xp:panel id="refresh">
<xp:section id="section1" initClosed="false">
<xp:panel id="innerRefresh">Section content</xp:panel>
</xp:section>
</xp:panel>
<xp:button value="refresh inner div" id="button3">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial"
refreshId="innerRefresh">
<xp:this.action><![CDATA[#{javascript://refresh}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button value="refresh outer div" id="button4">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial"
refreshId="refresh">
<xp:this.action><![CDATA[#{javascript://refresh}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button value="refresh section" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial"
refreshId="section1">
<xp:this.action><![CDATA[#{javascript://refresh}]]></xp:this.action>
</xp:eventHandler></xp:button>
<xp:button value="full refresh" id="button2">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript://refresh}]]></xp:this.action>
</xp:eventHandler></xp:button>
By trying to refresh the sction in differen ways i saw nothing unusual if i pressed each button once or twice with about one secound in between, but if you press the button "refresh section" multiple times the section opens again. This effekt works in my IE8 and Firefox 19.0.2. I would recomend using a panel/div around your section and refresh it instead of the section direkt.
Update:
Try this, it creates up to 3 sections dynamical and each refreshable by its own button, and they will stay closed,
<xp:this.beforePageLoad><![CDATA[#{javascript:var sectioncount:java.util.Vector = #Explode("1,2,3",",");
viewScope.put("sectioncount",sectioncount);
viewScope.put("selectedSection", sectioncount)
}]]></xp:this.beforePageLoad>
<xp:checkBoxGroup id="checkBoxGroup1"
value="#{viewScope.selectedSection}">
<xp:this.defaultValue><![CDATA[#{javascript:return viewScope.get( "sectioncount" );}]]></xp:this.defaultValue>
<xp:eventHandler event="onchange" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:// full update //partial update}]]></xp:this.action>
</xp:eventHandler>
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:return viewScope.get( "sectioncount" );}]]></xp:this.value>
</xp:selectItems>
</xp:checkBoxGroup>
<xp:repeat id="repeat2" rows="30" var="varcollection"
repeatControls="true">
<xp:this.value><![CDATA[#{javascript:return viewScope.get( "sectioncount" );}]]></xp:this.value>
<xp:panel>
<xp:this.rendered><![CDATA[#{javascript:var vec:java.util.Vector = viewScope.get( "selectedSection" );
return #IsMember(varcollection,vec);
}]]></xp:this.rendered>
<xp:button value="refresh this section:" id="button3">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial"
refreshId="refresh">
<xp:this.action><![CDATA[#{javascript://refresh}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:panel id="refresh">
<xp:section id="section1" initClosed="false">
<xp:panel id="innerRefresh">
<xp:text>
<xp:this.value><![CDATA[#{javascript:var date:java.util.Date = new java.util.Date;
return date.toTimeString()}]]></xp:this.value>
</xp:text></xp:panel>
</xp:section>
</xp:panel>
</xp:panel>
</xp:repeat>

by clicking on one button invoke two other buttons

I would like by clicking on a button to "activate" the clicking of 2 other buttons.
I've put this ccjs in the onclick event:
document.getElementById("#{id:button28}").click();document.getElementById("#{id:button29}").click();
But then only button 28 gets clicked !
Then I tried putting this part1 of the code under the onclick event and part2 under the onmousedown event. Then I have to click 2 times this button before he actually does the job.
the code so far:
<xp:button value="Save" id="button26">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script>
<xp:executeClientScript>
<xp:this.script><![CDATA[document.getElementById("#{id:button29}").click();
></xp:this.script>
</xp:executeClientScript>
</xp:this.script></xp:eventHandler></xp:button><xp:button id="button29" value="button29">
<xp:eventHandler
event="onclick" submit="true" refreshMode="partial"
id="eventHandler21" refreshId="outsidePanel5">
<xp:this.action>
<xp:actionGroup>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:sessionScope.put("test","");// and some more code}]]>
</xp:this.script>
</xp:executeScript>
</xp:actionGroup>
</xp:this.action>
<xp:this.onComplete><![CDATA[document.getElementById("#{id:button28}").click();]]></xp:this.onComplete>
</xp:eventHandler></xp:button><xp:button value="button28" id="button28">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="outsideMogelijkheid">
<xp:this.action>
<xp:executeScript
script="#{javascript://some code}">
</xp:executeScript>
</xp:this.action>
</xp:eventHandler></xp:button>
If you want to run the SSJS in another button, you can actually call the eventHandler programmatically rather than triggering the button in CSJS. This will also perform better, because you're not switching between CSJS and SSJS all the time. The following code should work:
var eventHandler:com.ibm.xsp.component.xp.XspEventHandler = getComponent("button29");
eventHandler.getAction().invoke(facesContext, null);
eventHandler = getComponent("button28");
eventHandler.getAction().invoke(facesContext, null);
If these buttons execute SSJS code you need to add the code to click on the second button in the
onComplete event of the first button.
http://xpagesblog.com/XPagesHome.nsf/Entry.xsp?documentId=0574D334CB03EACF852578CB00667F54
Addition
Working example of onComplete not that it only works with partial refresh
<xp:button value="Save" id="button26">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[document.getElementById("#{id:button29}").click()]]>
</xp:this.script>
</xp:eventHandler></xp:button>
<xp:button id="button29" value="button29">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="computedField1">
<xp:this.action><![CDATA[#{javascript:viewScope.test="Almost Done"}]]>
</xp:this.action>
<xp:this.onComplete>
<![CDATA[document.getElementById("#{id:button28}").click();]]>
</xp:this.onComplete>
<xp:this.onError><![CDATA[alert("error")]]></xp:this.onError>
</xp:eventHandler></xp:button>
<xp:button value="button28" id="button28">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="computedField1">
<xp:this.script><![CDATA[alert("Button 28")]]></xp:this.script>
<xp:this.action>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:viewScope.test="Done"}]]>
</xp:this.script>
</xp:executeScript>
</xp:this.action></xp:eventHandler>
</xp:button>
<xp:br></xp:br>
<xp:text escape="true" id="computedField1" value="#{viewScope.test}"></xp:text>

Resources