XPages Dialog boxes stacking - dialog

I got the problem, that my dialog boxes are stacking each time I click the button that opens the dialog. So if I've clicked three times I get this:
I couldn't find out how to prevent this. No matter which button I click (OK does a partial refresh | Abbrechen (Cancel) does a full update) I get another box each time I click the button.
Code of the button that opens the dialog:
<xp:button value="Plan meeting" id="buttonPlanMeeting">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:try {
var c = getComponent("dPlanMeeting")
c.show();
} catch(e) {
dBar.error(location + e);
}}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
Code for the complete dialog box:
<xe:dialog id="dPlanMeeting" title="Plan meeting" keepComponents="true">
<xp:panel>
<xp:text escape="true" id="MBPlanMeeting">
<xp:this.value><![CDATA[#{javascript:specialstrings.getString("ccEsgDocWflContentEditInfos.dPlanMeeting.MBPlanMeeting")}]]></xp:this.value>
</xp:text>
</xp:panel>
<xe:dialogButtonBar>
<xp:button value="Ok" id="buttonDelegateOk" styleClass="lotusFormButton">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:try {
//will create a meeting for every day the visit is registered
var wfDoc:NotesDocument = docApplication.getDocument(true);
specialMeetingCreate(wfDoc);
var c = getComponent("dPlanMeeting");
c.hide();
var c = getComponent("dMeetingCreated")
c.show();
} catch (e) {
dBar.error(location + e);
}
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button value="Cancel" id="buttonDelegateCancel" styleClass="lotusFormButton">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:try {
var c = getComponent("dPlanMeeting");
c.hide();
} catch (e) {
dBar.error(location + e);
}
}]]></xp:this.action>
</xp:eventHandler></xp:button>
</xe:dialogButtonBar>
</xe:dialog>
Does this have anything to do with keepComponents? I've tried true and false, but the effect stays the same.
Any idea?

Ok it seems that the solution was just to set "keepComponents = false". I've tried that before, but now it'S working. I get the dialog box only once no matter how often I click the button

Related

how to define a conditional xp:confirm?

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}" />

Trying the Partial Refresh Optimizes by Sven Hasselbach

I set up a really simple little test page with this code:
<xp:panel id="panelAll">
<xp:panel rendered="#{javascript:(viewScope.vsPanelRed) ? true : false;}" style="background-color:rgb(255,0,0)">
Panel Red
</xp:panel>
<xp:panel
rendered="#{javascript:(viewScope.vsPanelRed) ? false : true;}"
style="background-color:rgb(0,255,0)">
Panel Green
</xp:panel>
</xp:panel>
<xp:br></xp:br>
<xp:panel id="panelMain">
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script>
<![CDATA[XSP.partialRefreshPost('#{id:panelAll}',{clearForm: true});]]>
</xp:this.script>
<xp:this.action><![CDATA[#{javascript:println( "in Click Button");
if (viewScope.vsPanelRed == true){
viewScope.vsPanelRed = false;
}else{
viewScope.vsPanelRed = true;
}
}]]>
</xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel><!-- panelMain -->
the action toggles the viewScope vsPanelRed from true to false and displays either the red panel or the green on. If I use the conventional refreshMode="partial" refreshId="panelAll" on the eventHandler for the onclick the panel toggles if I use the partialResheshPost as the blog says (and I think I have it entered correctly the partial refresh does not happen infact the action to toggle the vsPanelRed does not happen either. So I must have something wrong in the ![CDATA ] but I can't figure out why.
What am I missing?
Sven Hasselbach did not include support for event handlers in his optimized partial refresh. I have extended his solution to include support for this - see my blog post "XPages: Optimized partial refreshes for event handlers".
If you include my optimized version as a xp:scriptBlock on your XPage then you need to change your button to this:
<xp:button value="Label" id="button1">
<xp:eventHandler id="submitEventHandler" event="onclick" submit="false">
<xp:this.script>
<![CDATA[
XSP.partialRefreshPost(
'#{id:panelAll}',
{clearForm: true, submitid: '#{id:submitEventHandler}'}
);
]]>
</xp:this.script>
<xp:this.action><![CDATA[#{javascript:
println( "in Click Button");
if (viewScope.vsPanelRed == true){
viewScope.vsPanelRed = false;
}else{
viewScope.vsPanelRed = true;
}
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>

Can pagerControls have onclick events?

I've got a dynamic view that totals what's displayed on the screen using a viewScope variable and I want to have it reset my viewScope variable. It doesn't and it appears not to be executing any script I put in there.
<xp:pager partialRefresh="true" id="upperPager"
for="viewRowRepeat" styleClass="tsDynamicViewPager" pageCount="8"
alwaysCalculateLast="true">
<xp:pagerControl id="pagerControl4" type="First">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="viewRowRepeat">
<xp:this.action><![CDATA[#{javascript:dBar.info("pagerControl4 clicked");
clearColumnTotals();}]]></xp:this.action>
<xp:this.script><![CDATA[alert("Clicked!");]]></xp:this.script>
</xp:eventHandler>
</xp:pagerControl>
<xp:pagerControl id="pagerControl5" type="Group">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:dBar.info("pagerControl5 clicked");
clearColumnTotals();}]]></xp:this.action>
<xp:this.script><![CDATA[alert("Clicked!");]]></xp:this.script>
</xp:eventHandler>
</xp:pagerControl>
<xp:pagerControl id="pagerControl6" type="Last">
<xp:eventHandler event="onclick"
submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:dBar.info("pagerControl6 clicked");
clearColumnTotals();}]]></xp:this.action>
<xp:this.script><![CDATA[alert("Clicked!");]]></xp:this.script>
</xp:eventHandler>
</xp:pagerControl>
</xp:pager>
Needless to say, I don't know if I've coded it incorrrectly or if there isn't supposed to be any onclick event for pagerControls. I know the IDE doesn't show one for pagers themselves.
Connect your pager controls with a Dojo onclick event to execute client side code when pager control is clicked:
<xp:eventHandler
event="onClientLoad"
submit="false">
<xp:this.script><![CDATA[
dojo.query(".xspFirst").forEach(function(node) {
dojo.connect(node, "onclick", function() {
alert("First clicked");
});
});
dojo.query(".xspGroup").forEach(function(node) {
dojo.connect(node, "onclick", function() {
alert("Group clicked");
});
});
...
]]>
</xp:this.script>
</xp:eventHandler>
Classes rendered for pager controls are "xsp" + type like "xspFirst", "xspGroup" and "xspLast". Use this classes to get the controls.

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.

Selecting a Tab in a Tabbed Panel works the first time I click the button

After I click the button it goes to the next tab, however, if I click the previous tab to edit something then click the button again, nothing happens. Any idea why? Here is the button code:
<xp:button value="Next" id="buttonNext1">
<xp:eventHandler event="onclick"
submit="true" refreshMode="partial" refreshId="panelMain">
<xp:this.action><![CDATA[#{javascript:
viewScope.currentTab = "tpCompanyInformation";
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
I see you bound the SelectedTab or even the defaultTab value of to your viewScope.currentTab and set the viewScope variable in every button with your viewScope.currentTab = "id".
I would recomend setting the tab direct in the component by using getComponent('tabbedPanel').setSelectedTab('tabid').
As a little goody: maby this Code helps you it will Create two buttons ('back' & 'next'), no mather how much tabs you will add to your panel the buttons should always work as forward and backward buttons.
ButtonBack:
<xp:button id="button1" value="back">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="tabbedPanel1">
<xp:this.action><![CDATA[#{javascript:var panel:com.ibm.xsp.component.xp.XspTabbedPanel = getComponent('tabbedPanel1');
var list:Array = panel.getChildren().toArray();
var currentTab = panel.getSelectedTab();
for(var i = 0; i < list.length;i++){
if(currentTab.equals(list[i].id)){
if(i > 0)
panel.setSelectedTab(list[i-1].id);
else
panel.setSelectedTab(list[list.length - 1].id);
}
}
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
Button Next:
<xp:button value="Next" id="buttonNext1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="tabbedPanel1">
<xp:this.action><![CDATA[#{javascript://
var panel:com.ibm.xsp.component.xp.XspTabbedPanel = getComponent('tabbedPanel1');
var i:java.util.Iterator = panel.getChildren().iterator();
var currentTab = panel.getSelectedTab();
while(i.hasNext()){
if(currentTab.equals(i.next().id)){
if(i.hasNext())
panel.setSelectedTab(i.next().id);
else
panel.setSelectedTab(panel.getChildren().iterator().next().id);
}
}
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>

Resources