I have a link at the top of my page that is hidden until a radio button is changed from No to Yes or once the link is unhidden and has been clicked.
When my radio button changes from No to Yes, I fire a couple partial refreshes to unhide the link and another component on the page. For some reason I get an error when trying to unhide the link but not the other component.
Below is the code for the link, the radio button and the other component ( file Upload ) that gets unhidden as well. Perhaps someone can tell me what I am missing?
<xp:link escape="true"
text="Required: Click Here to Review COI"
id="linkReviewCOIRequirements"
value="http://domain.com/file.pdf"
target="_blank"
style="font-weight:bold; border-color:red;">
<xp:this.rendered><![CDATA[#{javascript:
viewScope.vendorAppReadCOI != "Yes" &&
( getComponent("rgVendorAPPGenLiabilityInsurYNI").getValue() == "Yes" || getComponent("rgVendorAPPWorkCompInsurYNI").getValue() == "Yes" || getComponent("VendorAPPProfLiabilityInsurYNI").getValue() == "Yes" ) }]]></xp:this.rendered>
<xp:eventHandler event="onclick" submit="true"
refreshMode="norefresh" id="eventHandler1" immediate="true">
<xp:this.action><![CDATA[#{javascript:viewScope.vendorAppReadCOI = "Yes"
}]]></xp:this.action>
</xp:eventHandler>
<xp:radioGroup id="rgVendorAPPGenLiabilityInsurYNI"
value="#{vendorApplication.vendorAPPGenLiabilityInsurYNI}"
defaultValue="No"
readonly="#{javascript:( sessionScope.vendorAppRenew == true ) ? true : false;}">
<xp:selectItem itemLabel="Yes" itemValue="Yes"
id="selectItem3" />
<xp:selectItem itemLabel="No" itemValue="No"
id="selectItem4" />
<xp:eventHandler event="onclick"
submit="false" id="eventHandler3">
<xp:this.script><![CDATA[
XSP.partialRefreshPost( "#{id:panelFU2}" ,
{
onComplete: function()
{
XSP.partialRefreshPost("#{id:linkReviewCOIRequirements}",
{
} )
}
} );
]]></xp:this.script>
</xp:eventHandler>
</xp:radioGroup>
<xp:panel id="panelFU2">
<xp:fileUpload id="fuVendorAPPGenLiabilityDoc"
value="#{vendorApplication.vendorAPPGenLiabilityDoc}"
readonly="#{javascript:( sessionScope.vendorAppRenew == true ) ? true : false;}">
<xp:this.rendered><![CDATA[#{javascript:getComponent("rgVendorAPPGenLiabilityInsurYNI").getValue() == "Yes";}]]></xp:this.rendered>
</xp:fileUpload>
</xp:panel>
Make sure you update for instance a xp:div instead and that this div contains your link. The error occurs because the xp:link is not present in the component tree when the code tries to refresh it.
Related
I am binding all of my components to a java source. One field is a radio button, and if the user selects "Other" as a value, then I must show an field labeled "Other" for the user to fill in.
I cannot use SJSS to get the value of the radio button as it doesn't exist yet. But then how do I found out what the user selected? In the change event should I set a viewScope var and refresh the secondary area and check for the value of the viewScope var?
<xc:cc_CommonFormField
id="cc_CommonFormField14"
label="Savings"
placeholder="">
<xp:this.facets>
<xp:radioGroup
xp:key="field"
id="radioGroup1"
value="#{doc.prjSav}">
<xp:selectItem
itemLabel="Financial"
itemValue="Financial">
</xp:selectItem>
<xp:selectItem
itemLabel="Safety"
itemValue="Safety">
</xp:selectItem>
<xp:eventHandler
event="onchange"
submit="true"
refreshMode="partial" refreshId="refresh1">
</xp:eventHandler>
</xp:radioGroup>
</xp:this.facets>
<div id = "refresh1">
<div id = "innerRefresh"
rendered="#{javascript:what to put here}">
</xc:cc_CommonFormField>
<xc:cc_CommonFormField placeholder="Enter Other Reason...">
<xp:this.facets>
<xp:inputText
id="inputText3"
xp:key="field"
value="#{doc.prjOther}">
</xp:inputText>
</xp:this.facets>
</xc:cc_CommonFormField>
</div>
</div>
Here is the code that is correct:
<xc:cc_CommonFormField
id="cc_CommonFormField14"
label="Savings and/or Revenue From the Project"
placeholder="">
<xp:this.facets>
<xp:radioGroup
xp:key="field"
id="radioGroup1"
value="#{doc.prjSav}">
<xp:selectItem
itemLabel="Financial"
itemValue="Financial">
</xp:selectItem>
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="norefresh">
<xp:this.script><![CDATA[var result=null;
for(var i=0; i<document.forms[0].elements.length; i++){
if(document.forms[0].elements[i].name=="#{id:radioGroup1}" ){
if(document.forms[0].elements[i].checked == true){
result=document.forms[0].elements[i].value;
break; //remove this if for check box groups and collect multiple values above instead
}}}
var sel = x$("#{id:innerRefresh}");
if (result == "Other")
{
x$("#{id:innerRefresh}").removeClass("scoHidden");
x$("#{id:innerRefresh}").addClass("scoVisible");
}
else
{
x$("#{id:innerRefresh}").removeClass("scoVisible")
x$("#{id:innerRefresh}").addClass("scoHidden");
}
XSP.partialRefreshGet("#{id:innerRefresh}")]]></xp:this.script>
</xp:eventHandler></xp:radioGroup>
</xp:this.facets>
</xc:cc_CommonFormField>
<div id="refresh1">
<xp:div id="innerRefresh" styleClass="scoHidden">
<xc:cc_CommonFormField placeholder="Enter Other Reason...">
<xp:this.facets>
<xp:inputText
id="inputText3"
xp:key="field"
value="#{doc.prjOther}">
</xp:inputText>
</xp:this.facets>
</xc:cc_CommonFormField>
There are 2 approaches to solve this:
- server side rendering using SSJS
- client side rendering using JS
When you opt for the former, you have to submit your data (partial including the hidden div) to recompute your rendered property.
Client side: you render the div in any case, but give it a class attribute that maps to CSS display:none.
In your client side JS you add an onChange handler to the radio buttons and change the class to something visible (and back if others are unselected). This saves you from a server round trip.
Only caveat: (best handled in your Java) you need to dismiss an eventually entered value in the field for other if other wasn't selected.
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
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>
I would like to put a combox on an xpages so the user can choose to witch page he wants to go.
for example if he chooses google he would go to google.com etc
I tried :
<xp:comboBox id="comboBox1">
<xp:selectItem itemLabel="Google"
itemValue="Google">
</xp:selectItem>
<xp:selectItem itemLabel="Yahoo" itemValue="Yahoo"></xp:selectItem>
<xp:eventHandler event="onchange"
submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:var item = getComponent("comboBox1").getValue();
if (item == 'Google') {
window.location.href = 'http://google.com';
};
}]]>
</xp:this.action>
</xp:eventHandler>
</xp:comboBox>
You are mixing server-side Javascript with client-side Javascript.
Do this instead:
<xp:eventHandler event="onchange" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:
var item = getComponent("comboBox1").getValue();
if (item == 'Google') {
facesContext.getExternalContext().redirect("http://google.com");
};
}]]></xp:this.action>
</xp:eventHandler>
Try:
facesContext.getExternalContext().redirect("http://example.com")
This and more things are available on xpagescheatsheet.com. Note in addition to the printed cheatsheet there's a link to an online "URL Cheatsheet" that has a bunch or URL Examples.
Bind your combo to a document datasource field or to a scoped variable ?
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>