I have a clickable image in a multi-tab tabbed table. The onclick event has two action groups (under one parent action group) with conditions. Each action group has one action. The first action group condition is "return false". Its action is a confirm that says "Test 1". The second action group condition is "return true" and its action is a confirm that says "Test 2".
When the above clickable image is anywhere but inside the tabbed table except the default tab, it appears to ignore the condition tests and as a result, both actions are triggered. If the image is inside the default tab, or if it outside of the tabbed table, it works as expected, showing on the second action (Test 2).
Note: If I replace the confirm actions with execute script actions, the conditions work. It appears this is specific to confirm actions.
Here is a sample of the clickable image code.
<xp:image url="/my.gif" id="image1" alt="Click here" style="cursor:hand;height:16.0px;width:17.0px">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete" id="eventHandler1">
<xp:this.action>
<xp:actionGroup>
<xp:actionGroup condition="#{javascript:return false;}">
<xp:confirm message="Test 1"></xp:confirm>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:try{
var val = getComponent("cfMessage").getValue();
getComponent("cfMessage").setValue("test 1")}
catch(e){}}]]>
</xp:this.script>
</xp:executeScript>
</xp:actionGroup>
<xp:actionGroup condition="#{javascript:return true;}">
<xp:confirm message="Test 2"></xp:confirm>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:try{
var val = getComponent("cfMessage").getValue();
getComponent("cfMessage").setValue(val+", test 2")}
catch(e){}}]]>
</xp:this.script>
</xp:executeScript>
</xp:actionGroup>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:image>
The tabbed table that contains this code is unexceptional. I drug a new tabbed table control onto the page, created two tabs, and added clickable images to both tab panels.
Thoughts?
As you already noticed, it's not related to Tabbed panel.
What I found is that after a partial refresh on the component, XPages does not care condition attribute if it has client side interaction.
It seems like a bug (and a similar one is known since 8.5.2)
I would create two different images with different set of actions and control visibility with rendered tags.
Related
UPDATED at bottom...
I have a custom control that contains an input field with typeAhead enabled:
<xp:inputText id="UTAN1" value="#{document1.UTAN}"
maxlength="5" styleClass="dbListFieldData" style="width:60px;font-size:13px;">
<xp:typeAhead mode="full" minChars="2">
<xp:this.valueList><![CDATA[#{javascript:var key = getComponent("UTAN1").getValue();
var path = new Array("","utans.nsf")
#Unique(#DbLookup(path,"(UTAN Lookup)",key,1,"[PARTIALMATCH]"));}]]></xp:this.valueList>
</xp:typeAhead>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="utanPanel1">
<xp:this.action>
<!-- DO SOME STUFF -->
</xp:this.action>
</xp:eventHandler>
</xp:inputText>
If I use the control inline on an xpage, typeAhead works fine.
However, if I insert the control in a dialog and call it to open:
<xp:link escape="true" id="link3" styleClass="dbListFieldData" >
<xp:eventHandler event="onclick" submit="false" id="eventHandler3">
<xp:this.script><![CDATA[XSP.openDialog('#{id:miniDialogUTAN1}');]]></xp:this.script>
</xp:eventHandler>
<xp:image id="image2" url="/edit2.png" style="height:16px;width:16px;" alt="Edit UTAN"></xp:image>
</xp:link>
The typeAhead seems to be partly crippled.
If the field is already empty, suggestions comes up fine.
If the field has an existing value, backspacing only shows the existing value as a suggestion.
Overwriting the value entirely gives no suggestions at all.
The only thing that will get the typeAhead working is to change the value and hit Enter. Basically, trigger an onChange. After that, ALL the typeAhead fields start working.
Any ideas on how to correct this behavior? FYI, I'm an xpages noob, so please go easy on me.
UPDATE 6/29/2021:
I'm still desperately in need of help with this. I've been playing around with Firebug and found something interesting.
In type-aheads on a normal Xpage form (where type-ahead works), entering each character calls a POST every time. However, when the type-ahead is in a dialog, typing in characters calls GETs. If I hit Enter or tab out of the field (triggering onChange), I get a single POST, and then clicking back into the field and typing, it starts using GETs again and it pulls valid suggestions as long as I don't backspace and type something different. Then the suggestions go away. This would be expected since GETs are cached and POSTs are not.
So what's going on with type-aheads in dialogs that makes them use GET, and how to I force it to use POST on every key press?
To people of the future...
After weeks of fretting over this and finally giving up I stumbled upon the solution by accident.
My dialog opens in read mode. I have both an Edit button and a Cancel button at top and bottom that were originally hard coded in both spots of the dialog custom control. Later I went to clean some stuff up and decided to create a single custom control for both sets of buttons. Once I did that, suddenly the type-aheads worked!
It turns out that when I copied and pasted the XML from the (supposedly) duplicate button panels to the new custom control, I had copied from the bottom button panel (which I rarely used while testing).
When I compared the XML for the top and bottom Edit Buttons, I found that the top one had the following attributes in the onClick:
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
while the bottom one had:
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="dialogOuterPanel1">
So, the full refresh broke my type-aheads and a partial refresh fixed them.
My Xpages application is showing a strange problem. I have an XPage with with a tab control (2 tabs) and each tab has a dynamicviewpanel and a delete button. Each tab shows a different view depending on a condition. The first tab works completely fine for both myself and the user but the second tab, the view shows the correct documents and the delete button works fine for me and a fellow developer but when the user clicks on the delete button in the second tab they receive the error.
<xp:button id="DeleteContract" value="Delete Contract ID">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:actionGroup>
<xp:confirm
message="Are you sure?">
</xp:confirm>
<![CDATA[#{javascript:var viewPanel=getComponent
("dynamicViewPanel3");
var docIDArray=viewPanel.getSelectedIds();
for(i=0; i < docIDArray.length; i++){
var docId=docIDArray[i];
var doc=database.getDocumentByID(docId);
doc.remove(true);
}}]]>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
The error being presented on the browser is "Exception occurred calling method NotesDocument.remove(boolean) null"
The logs do not tell me much either
All the permissions are the same for each tab etc so it shouldn't be a permissions issue. Why would this be occurring?
Discovered the logic in the solution was working after all. It was bad feedback that was making us think the specific user could delete in one tab but not the other. After discovering the user could not delete from any tab, we found that they were a member of another lotus notes group that we could assign deletion privileges to and then all was working for them. Stupid I know, but it was confusing feedback that made me assume the user could delete in one tab but not the other. Thanks to all who contributed
I've working code to open dialog box using SSJS code to show error or warning to user when user click submit button. This button appears at the top of the xpage.
Applied the modified version of the above code in another application but instead of top of xpage, put button in section. If comboBox1 has initial value it is suppose to popup the dialog box. But it is not working. The client side validation is off in working as well as non working application. Why this code is not working? Where to check?
Here is code for a section button:
<xp:button value="Must click to Assign Quote Number" id="button6" style="width:207.0px">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete" immediate="false" save="true">
<xp:this.action>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:var comboBox1:com.ibm.xsp.component.xp.XspSelectOneMenu = getComponent("comboBox1");
var a=comboBox1.getValue();
if ( a=="Assign the PE Staff"){
var d=getComponent('dialog2');
d.show();
}
}]]></xp:this.script>
</xp:executeScript>
</xp:this.action></xp:eventHandler>
</xp:button>
Things to check off the top of my head:
Check that Ext Lib is loaded properly in new app (check application properties)
Check that namespace for ExtLib is on the new page (drag any Ext Lib control on the page, and this will be added for you)
Check that resources from the first page are on the new one (script libraries, etc)
Try print("var a=" + a) to see if comboBox1 is giving you a value (check your server log.nsf)
If you give more info on what is happening when it doesn't work then we might be able to suggest more things to check.
I have an application with one XPage. It has these custom controls(cc):
ccHeader
ccMenu
ccContent
ccFooter
Custom control ccContent has a combobox, with list of Views in sessionScope and dynamic view panel from extension library for XPages. This combobox has an event OnChange defined to partial update dynamic view.
What do I need?: Combobox with view list will be deleted and after that I need to assign this partial update function to five links, which are located on ccMenu custom control. So, i click on link in ccMenu, it returns some view name, assigns it to dynamic view and makes partial update.
How to get id of this dynamic view in ccMenu to call partial update?
Assuming what you mean is that you want to have a clean way to let the buttons know which area to partial-refresh when changed:
You could add a property to the ccMenu control along the lines of "viewRefreshId" and pass in the ID of the area to refresh, so you'd end up with a button like this:
<xp:button id="viewChanger1" value="View 1">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="${compositeData.viewRefreshId}">
<xp:this.action><![CDATA[#{javascript: viewScope.selectedView = 'View 1' }]]></xp:this.action>
</xp:eventHandler>
</xp:button>
Now, there's a question of whether you should try to pass in an ID from something contained within another CC from the main XPage, and I try to avoid that - it would PROBABLY work, but it's a bit messy. I tend to architect similar things so that the part to be refreshed is directly on the XPage (which is to say, I don't use "content" custom controls), so I end up with something like this:
<xc:viewSelector viewRefreshId="dynamicViewContainer"/>
<xp:div id="dynamicViewContainer">
<xe:dynamicView>
<xe:this.data>
<xp:dominoView var="view1" viewName="#{viewScope.selectedView}"/>
</xe:this.data>
</xe:dynamicView>
</xp:div>
The extra container div comes from experience that I had a while ago where refreshing the dynamic view directly caused rendering problems, but I don't know if that's still the case (or if I had run into some other problem).
I'm setting value of input field on click event of the check box. The editable field is used to validate group of check boxes. This code works in one xpage. When I tried to replicate this code in other xpage, it is not working.
Here is a working code:
<xp:checkBox
text="pH"
id="checkBox1"
value="#{document1.PH}"
checkedValue="pH">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="partial"
refreshId="routineSectionInput1"
execMode="partial">
<xp:this.action>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:var
checkBox1:com.ibm.xsp.component.xp.XspInputCheckbox = getComponent("checkBox1");
var routineSectionInput1:com.ibm.xsp.component.xp.XspInputText = getComponent("routineSectionInput1");
if (checkBox1.getValue()=='pH'){
routineSectionInput1.setValue('Selected');
} else {
routineSectionInput1.setValue('');
}}]]></xp:this.script>
</xp:executeScript>
</xp:this.action>
</xp:eventHandler>
</xp:checkBox>
I used same field names and same code on another xpage and it is not working. What I'm doing wrong?
Best regards
When you work with component logic where binding is involved, don't go after the component, go after the data that defines their value. So your code would rather look like this:
<xp:checkBox text="pH" id="checkBox1"
value="#{document1.PH}" checkedValue="pH">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="partial"
refreshId="routineSectionInput1"
execMode="partial">
<xp:this.action>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:var chkValue = document1.getItemValueString("PH");
viewScope.routineSection = (chkValue=="pH") ? "Selected" : "";
}]]></xp:this.script>
</xp:executeScript>
</xp:this.action>
</xp:eventHandler>
</xp:checkBox>
<xp:text id="routineSectionInput1" value="#{viewScope.routineSection}"></xp:text>
Hope that helps
If there are validation errors or components have data that is of the wrong data type (e.g. text that cannot be parsed as a number in a component bound to a Number field, so conversion errors), any SSJS will fail.
I'd recommend adding a print statement at the start of the SSJS to check whether it's firing. (If you're more confident with XPages, use a PhaseListener to check the correct phase is being triggered).
Also, it's worth adding an Display Errors control to catch any validation errors caught during the partial refresh, ensuring it's within the refresh area (otherwise the errors will not be displayed in the browser).
"Process data without validation" option may be of use here, it you want to skip validation. Note that conversion errors will still prevent SSJS running.
As Stephan says, use the datasource rather than the component, if possible. The datasource will have been updated before the SSJS fires.
Removed the checkboxes, compacted the database with -c and added back those checkboxes with the same code. It is working now.