Trying to get the value of a listBox with Select2 - xpages

I have the latest extension library installed running on the latest version of Domino. I am using a simple listBox with values from a DBColumn ( which works to populate the listBox ).
However, I can't seem to get the selected value of the listBox. I've poked around the net a while and found several different things which I have tried unsuccessfully. Then I started reading about having to install other libraries etc. Now I am confused. Below is my code. All I want to do is get the selected value from the listBox once it changes but I really want to use the select2 features to search the listBox. Can someone point me in the right direction on how to get the selected value when it changes?
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:bx="http://www.openntf.org/xsp/bootstrap">
<xp:scriptBlock id="scriptBlock2">
<xp:this.value>
<![CDATA[
$(document).ready(
function() { x$( "#{id:listBoxProperties}" ).select2()
.on("change", function(e) { XSP.partialRefreshPost(
"#{id:computedField2}" );
}
}
);
]]>
</xp:this.value>
</xp:scriptBlock>
<xp:panel>
<xp:listBox id="listBoxProperties" value="#{viewScope.selectedProperty}"
style="width:250px">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:listOfProperties = #DbColumn( #DbName(), 'vwAuditDocsByPropertyNo', 1 );
if( #IsError( listOfProperties ) )
"Error looking up properties: " + listOfProperties;
listOfProperties;
}]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="true"
refreshMode="complete">
</xp:eventHandler></xp:listBox>
<bx:select2PickerCombo id="select2Property"
for="listBoxProperties" placeHolder="-Select a Property-"
binding="#{javascript:viewScope.selectedProperty}">
</bx:select2PickerCombo>
<xp:br></xp:br>
<xp:text escape="true" id="computedField1"
value="#{javascript:viewScope.selectedProperty;}">
</xp:text>
<xp:text escape="true" id="computedField2">
<xp:this.value><![CDATA[#{javascript:getComponent( "listBoxProperties").getValue()}]]></xp:this.value>
</xp:text>
</xp:panel>
</xp:view>

I have tested your scenario and can verify that the onchange event of the lixtBox does not fire when using bx:select2PickerCombo to style the listBox as a Select2 control. If you remove the use of bx:select2PickerCombo, the onchange event fires as expected. Here's a simple example (without the use of bx:select2PickerCombo):
<xp:listBox id="listBoxProperties" value="#{viewScope.selectedProperty}" style="width:250px">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:["1","2","3"]}]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="refreshField"></xp:eventHandler>
</xp:listBox>
<!--<bx:select2PickerCombo id="select2Property" for="listBoxProperties" placeHolder="-Select a Property-" binding="#{javascript:viewScope.selectedProperty}"></bx:select2PickerCombo>-->
<xp:text escape="true" id="refreshField" value="#{javascript:viewScope.selectedProperty;}"></xp:text>
You need to manually add Select2 to your listBox to get the onchange event to work. See this answer for more details: Bootstrap4XPages plugin: how to catch a change event with Select2 Picker?

Related

How to do a partial refresh of multiple items in Xpages correctly

I have read many of the blog posts on doing a partial refresh on more than one element, but I cannot seem to get it to work.
I made a "toy" example, an Xpage with two fields and one button. Both fields are bound to a sessionScope counter. The button increments the counter and does a partial refresh on the containing panel.
I want to do a partial refresh on the first field, which is not in the panel [in my real Xpage the two fields are very far apart on the form.
Tried many different things to get this to work, but none worked. Is it even possible to do this?
<?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"
xmlns:xc="http://www.ibm.com/xsp/custom"
style="background-position:center left"
xmlns:on="http://www.openntf.org/domino/xsp" viewState="nostate"
xmlns:debug="http://www.openntf.org/xsp/debugtoolbar">
First Var<br></br>
<xp:text escape="true" id="computedField1" value="#{sessionScope.number}">
</xp:text>
<br></br>
<xp:br></xp:br>
<br></br>
Second Var<xp:panel id="pnl1">
<xp:text escape="true" id="computedField2" value="#{sessionScope.number}">
</xp:text>
<br></br>
<br></br>
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="pnl1" execMode="partial"
execId="pnl1">
<xp:this.action><![CDATA[#{javascript:var t = sessionScope.number + 1;
sessionScope.number = t;}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:view>
Read Knut's link and got this to work. I made a change to the event handler of the button and it worked. Here is the code:
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="pnl1" execMode="partial"
execId="pnl1">
<xp:this.action><![CDATA[#{javascript:var t = sessionScope.number + 1;
sessionScope.number = t;}]]></xp:this.action>
<xp:this.onComplete><![CDATA[XSP.partialRefreshPost("#{id:computedField1}");]]></xp:this.onComplete>
</xp:eventHandler>
Use XSP.partialRefreshPost(): http://avatar.red-pill.mobi/tim/blog.nsf/d6plinks/TTRY-84B6VP

dynamic combobox does not update it's binding scopevar when it's items get updated

I ran in some troubles with a combobox. Here is a copy/paste example code to demonstrate my problem.
<xp:this.beforeRenderResponse><![CDATA[#{javascript://
viewScope.value1 = "document.getItemValueString('value1')" + viewScope.document;
viewScope.value2 = "document.getItemValueString('value2')" + viewScope.document;}]]>
</xp:this.beforeRenderResponse>
<xp:button
value="change document"
id="button1">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript: viewScope.document = new Date().getMilliseconds()//}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<br></br>
<xp:comboBox id="comboBox1" value="#{viewScope.value3}">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:viewScope.value1;}]]></xp:this.value>
</xp:selectItems>
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:viewScope.value2;}]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler
event="onchange" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript://}]]></xp:this.action>
</xp:eventHandler>
</xp:comboBox>
<br></br>
<xp:text escape="true" id="computedField1" value="#{viewScope.value1}"></xp:text>
<br></br>
<xp:text escape="true" id="computedField2" value="#{viewScope.value2}"></xp:text>
<br></br>
<xp:text escape="true" id="computedField3" value="#{viewScope.value3}"> </xp:text>
What did I try to accomplish: I have a combobox with two or more calculated selectItems. They depend on which document is currently selected. To demonstrate a switch of documents I use the button change document in this example. When a new document is selected the beforeRenderResponse event
gets the itemvalues from the document and puts them in a viewscope var. I have to separate the two values so I can't use a Array for them. That's all working so far but: If I select a value e.g. value2(timestamp1) and do a switch document the viewScope.value3 where the combobox is bound to did not update.
It displays the old value2 from the last document until I trigger its onChange event.
How can I force the comboBox to update its viewScope var with its selectItems?
Found a solution wich works at least for my copy/pase example:
<xp:this.beforeRenderResponse><![CDATA[#{javascript://
viewScope.value1 = "document.getItemValueString('value1')" + viewScope.document;
viewScope.value2 = "document.getItemValueString('value2')" + viewScope.document;
var list = new Array();
list.push(value1);
list.push(value2);
if(!#IsMember(viewScope.value3,list)){
viewScope.value3 = list[0];//list.pop();
}}]]>
</xp:this.beforeRenderResponse>
Now the viewScope.value3 gets changed to value1 if the documents is changed.

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 Dynamic dojo dialog control

I have a list of products (created using a repeat control) and wish to click on a particular product and bring up a dialog with further information about that particular product. I don't really want to generate dijit.dialog thing for every single product on that page, so how can I do this dynamically possibly using AJAX and partial refresh.
A similar non xpages example can be seen here: http://www.replacementkeys.co.uk/window?dir=asc&limit=12&mode=grid&order=position - where you hover over an image and a quick view button comes up, which then dynamically loads the content for that product.
Any ideas would be truly appreciated.
We build the dialog outside the repeat control and then the action that launches or shows it also sets a viewScope variable that is used UNID for the data source in the dialog. Just make sure you refresh the contents of the dialog as you open it...
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:this.data>
<xp:dominoView var="promptView" viewName="dlgBoxes">
</xp:dominoView>
</xp:this.data>
<xp:panel>
<xp:repeat id="repeat1" rows="30" value="#{promptView}" var="promptEntry">
<xp:panel tagName="div">
<xp:text escape="true" id="computedField1" value="#{promptEntry.dlgName}">
</xp:text>
 
<xp:button value="details" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:
var pe:NotesViewEntry = promptEntry;
viewScope.put("dlgDocUnid", pe.getUniversalID());
getComponent("dialog1").show();
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:repeat>
</xp:panel>
<xe:dialog id="dialog1" keepComponents="false" partialRefresh="true">
<xe:this.title><![CDATA[#{javascript:
var unid = viewScope.get("dlgDocUnid");
if(!unid) return "";
var doc:NotesDocument = database.getDocumentByUNID(unid);
return doc.getItemValueString("dlgName");}]]></xe:this.title>
<xp:panel>
<xp:this.data>
<xp:dominoDocument var="dlgDoc" formName="dlgBox" action="openDocument">
<xp:this.documentId><![CDATA[#{javascript:viewScope.get("dlgDocUnid");}]]></xp:this.documentId>
</xp:dominoDocument>
</xp:this.data>
<xp:text escape="true" id="computedField2" value="#{dlgDoc.Title}">
</xp:text>
<xp:br></xp:br>
<xp:br></xp:br>
<xp:text escape="true" id="computedField3" value="#{dlgDoc.dlg}">
</xp:text>
</xp:panel>
</xe:dialog>
</xp:view>
Happy coding
/Newbs
You can combine your repeat control with the Extension Library dialog control in order to be able to launch a dialog when the user clicks on the individual row. Chris Toohey has created an excellent article called Popup Dialog Forms from Views in XPages that demonstrates this.

How do I get the value of nth Edit box in a repeat control?

I have an EditBox control in a repeat control. Its iteration formula is:
return 5;
It is successfully displaying 4 edit boxes (the starting index is set to 1).
In SSJS, how can I get the value of the nth Edit Box?
You could set a sessionScope variable (or any scope variable) on the onchange event of the edit box and then in your SSJS reference the sessionScope variable. Here is some sample code, the bottom bit just shows your sessionScope variables on the page.
<?xml version="1.0" encoding="UTF-8"?>
<xp:repeat id="repeat1" rows="30" value="#{javascript:5}"
indexVar="rptIndex">
<xp:inputText id="inputText1">
<xp:eventHandler event="onchange" submit="true" refreshMode="complete">
<xp:this.action>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:sessionScope['text'+rptIndex] = getComponent("inputText1").getValue()}]]></xp:this.script>
</xp:executeScript>
</xp:this.action></xp:eventHandler></xp:inputText>
</xp:repeat>
<xp:table styleClass="debug">
<xp:tr>
<th>Variable Name</th>
<th>Variable Content</th>
</xp:tr>
<xp:repeat id="varRepeat" rows="30" value="#{javascript:sessionScope.keySet();}" var="scopeData">
<xp:tr>
<xp:td>
<xp:text escape="true" id="varName" value="#{javascript:scopeData}" />
</xp:td>
<xp:td>
<xp:text escape="true" id="varValue" value="#{javascript:sessionScope.get(scopeData)}" />
</xp:td>
</xp:tr>
</xp:repeat>
</xp:table>
</xp:view>
When you add a submission to an onChange event you create a rather chatty application - might bite you. The solution for setting the focus is rather different. First: focus is a client side operation, so you need a client script that 'knows what control is the first failure. The good news: XPages adds to all fields that failed a server side validation the attribute aria-invalid=true.
So you can use a dojo.onLoad script that queries that and sets the focus to the first member of the result. See also http://dontpanic82.blogspot.com/2011/07/xpages-styling-invalid-field.html
And for the query syntax:
http://dojotoolkit.org/reference-guide/1.7/dojo/query.html
Repeats are fun to deal with to say the least. If you look at examples in the teamroom template mobileThread custom control you'll see a repeat for displaying a list of replies, you'll also notice a lot of javascript to go along with it as for example running script on one button click would run on all buttons in the repeat.
If you are looking for the validation problem stwissel's solution looks the best. If this is something else and at some point you just need the value of any given edit box, maybe you should think about something like:
var domEl = dojo.byId(' <repeatControlId> ');
var textBoxes = domEl.getElementsByTagName("input");
var certainValue = textBoxes[3].value;
Now certainValue contains the value of a given edit box.
haven't tried this out, might need a little tweaking but the general idea should work I would think.
added another comment so i could add code.
Did a quick test and works fine for me, see my example below. Hope it helps. Try adding some print outs to see is it getting each bit.
<xp:repeat id="TestRepeat" rows="100" var="rowData"
indexVar="commentIndex" first="0" rendered="true">
<xp:this.value><![CDATA[#{javascript:
var dataArray = new Array();
dataArray.push(" Test");
dataArray.push(" Test");
dataArray.push(" Test");
dataArray.push(" Test");
dataArray.push(" Test");
return dataArray;
}]]></xp:this.value>
<xp:panel>
<xp:label value="Test"></xp:label>
<xp:inputText id="inputText1" value="Test" defaultValue="Test">
</xp:inputText>
<xp:br></xp:br>
</xp:panel>
</xp:repeat>
<xp:button value="Test" id="button1">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script>
<xp:executeClientScript>
<xp:this.script><![CDATA[
var domEl = dojo.byId('#{id:TestRepeat}');
var textBoxes = domEl.getElementsByTagName("input");
alert( "Value 1: " + textBoxes[0].value);
]]></xp:this.script>
</xp:executeClientScript>
</xp:this.script>
</xp:eventHandler>
</xp:button>

Resources