filter in xe:dominoViewListTreeNode - xpages

How to write regular expression for NOT to include view name start with '(' in xe:dominoViewListTreeNode
Generally we use expression to include view name like:
<xe:dominoViewListTreeNode filter='All.*' ...>
There is the code:
<xe:navigator
id="navigator1"
xp:key="facet_3"
expandable="false"
>
<xe:this.treeNodes>
<xe:repeatTreeNode
loaded="true"
indexVar="index"
var="crrView"
value="#{javascript:return database.getViews();}"
>
<xe:this.children>
<xe:dominoViewListTreeNode
folders="false"
label="#{javascript:crrView.getName()}"
submitValue="#{javascript:crrView.getName()}"
enabled="true"
filter="^\w+.*"
>
<xe:this.selected><![CDATA[#{javascript:if(context.getSubmittedValue()===null){
crrView.getName().equals("Pending \\By Status");
}
else{
crrView.getName().equals(context.getSubmittedValue());
}}]]></xe:this.selected>
</xe:dominoViewListTreeNode>
</xe:this.children>
</xe:repeatTreeNode>
</xe:this.treeNodes>
<xp:eventHandler
event="onItemClick"
submit="true"
refreshMode="partial"
refreshId="oneuilayout"
>
<xe:this.action>
<xp:executeScript
script="# {javascript:viewScope.viewName = context.getSubmittedValue();}"
>
</xp:executeScript>
</xe:this.action>
</xp:eventHandler>
</xe:navigator>
Any idea!
-MAK

Use filter="[^(]+.*" for selecting all viewnames which don't start with "(" or filter="\w+.*" for viewnames which starts with a letter, digit or underscore.
Example for testing:
<xe:navigator id="navigator1">
<xe:this.treeNodes>
<xe:dominoViewListTreeNode var="viewName" folders="false"
enabled="true" filter="[^(]+.*"
href="#{javascript:viewName}" />
</xe:this.treeNodes>
</xe:navigator>

Related

Are xp:dataContext variables read-only?

From examples I've seen in the Mastering XPages book and around the web, an xp:dataContext variable should be writable but I can't get it to work.
Below is a simplified version of my code. A button calls an xe:dialog containing a panel with a dataContext variable attended and initial value of "", expecting to be able to write to it from the radioGroup data binding. When the radio is set to a certain value (in this case, != "Yes") I want to unhide a div but it doesn't work. The div does not appear and the txt1 computed text field never changes to reflect the value of the radio.
I have tried both an onclick and onchange event handler but neither seems effective. Are dataContext variables read-only?
<?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:button id="btn" value="Button">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial">
<xp:this.action><![CDATA[#{javascript:getComponent('dlg').show()}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xe:dialog id="dlg" title="Dialog">
<xp:panel id="panel1" readonly="false">
<xp:this.dataContexts>
<xp:dataContext var="attended" value="" />
</xp:this.dataContexts>
<xp:radioGroup id="activityAttended" value="#{attended}">
<xp:selectItem itemLabel="Yes" />
<xp:selectItem itemLabel="No" />
<xp:selectItem itemLabel="Maybe" />
<xp:eventHandler id="event1" event="onclick" submit="true"
refreshMode="partial" refreshId="target" />
</xp:radioGroup>
<xp:div id="target">
radio: <xp:text id="txt1" value="#{attended}" />
<xp:div id="div1" rendered="#{attended != 'Yes'}">
<xp:text id="txt2" value="#{attended}" />
</xp:div>
</xp:div>
</xp:panel>
</xe:dialog>
</xp:view>
To my knowledge, you can't assign to the variable name for a dataContext. What you could do would be to make the value bound to something that contains another value, like a Map or custom object, and then alter properties on that.
For example, if you made it like var="contextProps" value="${javascript:new java.util.HashMap()}", you could then do things like #{contextProps.attended != 'Yes'} and value="#{contextProps.attended}". Usually, you'll want a more-fleshed-out object than a generic HashMap for this, but it can serve as an example or a useful container in a pinch.

Custom control inside repeat can't see rowData in one custom property, but work in other

I have following custom control:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.beforePageLoad><![CDATA[#{javascript:compositeData.id = this.getId();
if (!compositeData.body_class) {compositeData.body_class='panel-body'};
if (!compositeData.panel_id) {compositeData.panel_id='section'+compositeData.id};}]]></xp:this.beforePageLoad>
<xp:panel>
<xp:this.styleClass><![CDATA[#{javascript:"ccSectionPanel panel " + compositeData.panel_class + ""}]]></xp:this.styleClass>
<xp:this.attrs>
<xp:attr name="id">
<xp:this.value><![CDATA[#{javascript:compositeData.panel_id}]]></xp:this.value>
</xp:attr>
</xp:this.attrs>
<xp:panel styleClass="panel-heading" style="cursor:pointer;">
<xp:this.attrs>
<xp:attr name="id">
<xp:this.value><![CDATA[#{javascript:compositeData.panel_id + "_heading"}]]></xp:this.value>
</xp:attr>
<xp:attr name="href">
<xp:this.value><![CDATA[#{javascript:"#" + compositeData.panel_id + "_section"}]]></xp:this.value>
</xp:attr>
<xp:attr name="data-toggle" value="collapse"></xp:attr>
</xp:this.attrs>
<xp:link escape="true" styleClass="panel-title"
text="#{javascript:compositeData.titleBarText}">
<xp:this.attrs>
<xp:attr name="id">
<xp:this.value><![CDATA[#{javascript:compositeData.panel_id + "_title"}]]></xp:this.value>
</xp:attr>
</xp:this.attrs>
<xp:this.id><![CDATA[${javascript:compositeData.panel_id + "_title"}]]></xp:this.id>
</xp:link>
</xp:panel>
<xp:panel>
<xp:this.styleClass><![CDATA[#{javascript:"panel-collapse collapse" + (compositeData.initClosed ? "" : " in")}]]></xp:this.styleClass>
<xp:this.attrs>
<xp:attr name="id">
<xp:this.value><![CDATA[#{javascript:compositeData.panel_id + "_section"}]]></xp:this.value>
</xp:attr>
</xp:this.attrs>
<xp:panel
styleClass="#{javascript:compositeData.body_class}">
<xp:callback facetName="panelBody" id="panelBody"></xp:callback>
</xp:panel>
<xp:panel rendered="#{javascript:compositeData.footer}"
styleClass="panel-footer">
<xp:callback facetName="panelFooter" id="panelFooter"></xp:callback>
</xp:panel>
</xp:panel>
</xp:panel>
</xp:view>
I use it in a repeat control:
<xp:repeat id="repeat1" rows="30" value="#{view1}"
var="repEntry" indexVar="index" repeatControls="false">
<xp:panel>
<xp:this.data>
<xp:dominoDocument var="doc"
action="openDocument"
documentId="#{javascript:repEntry.getNoteID()}"
ignoreRequestParams="true">
</xp:dominoDocument>
</xp:this.data>
<xc:ccSectionPanel initClosed="false"
panel_class="#{javascript:repEntry.getColumnValue('class')}"
footer="#{javascript:sessionScope.isAdmin}"
rendered="#{javascript:repEntry.getColumnValue('Status') == '1' || sessionScope.isAdmin}">
<xc:this.titleBarText><![CDATA[#{javascript:repEntry.getColumnValue('Title') + (repEntry.getColumnValue('Status') != '1' ? ' (скрыто)' : '')
}]]></xc:this.titleBarText>
<xp:this.facets>
<xp:panel xp:key="panelFooter">
<xp:button value="Редактировать"
id="button2" styleClass="btn btn-xs">
<i
class="glyphicon glyphicon-pencil">
</i>
<xp:eventHandler event="onclick"
submit="true" refreshMode="complete">
<xp:this.action>
<xp:openPage
name="/index.xsp" target="editDocument"
documentId="#{javascript:repEntry.getNoteID()}">
</xp:openPage>
</xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button
value="#{javascript:repEntry.getColumnValue('Status') != '1' ? 'Показать' : 'Скрыть'}"
id="button3" styleClass="#{javascript:'btn btn-xs'}">
<i
class="#{javascript:repEntry.getColumnValue('Status') != '1' ? 'glyphicon glyphicon-eye-open' : 'glyphicon glyphicon-eye-close'}">
</i>
<xp:eventHandler event="onclick"
submit="true" refreshMode="partial" disableValidators="true"
refreshId="content">
<xp:this.action><![CDATA[#{javascript:if (repEntry.getColumnValue('Status') == '1') {
doc.replaceItemValue('Status','0');
doc.replaceItemValue('Author',sessionScope.User.UserName);
doc.save();
} else {
doc.replaceItemValue('Status','1');
doc.replaceItemValue('Author',sessionScope.User.UserName);
doc.save();
}}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:text escape="false"
id="computedField2" styleClass="btn btn-xs">
<xp:this.value><![CDATA[#{javascript:'<i class="glyphicon glyphicon-user"></i>' + repEntry.getColumnValue('Author') + ' <i class="glyphicon glyphicon-time"></i>' + repEntry.getColumnValue('$1')
}]]></xp:this.value>
</xp:text>
</xp:panel>
<xp:panel xp:key="panelBody">
<!-- <xp:this.data>
<xp:dominoDocument var="doc" action="openDocument"
documentId="#{javascript:repEntry.getNoteID()}"
ignoreRequestParams="true">
</xp:dominoDocument>
</xp:this.data> -->
<xp:inputRichText
id="inputRichText2" value="#{doc.Body}" readonly="true"
rendered="false">
</xp:inputRichText>
<xp:text escape="false"
id="computedField1">
<xp:this.value><![CDATA[#{javascript:doc.getDocument().getFirstItem("Body").getMIMEEntity().getContentAsText(); }]]></xp:this.value>
</xp:text>
</xp:panel>
</xp:this.facets>
</xc:ccSectionPanel>
</xp:panel>
</xp:repeat>
When i set cumputed properties,
It works, but when i set panel_id to something relative to repEntry or doc, it throws error (repEntry is undefined). I can set "Create controls at page creation", but then I lose advantages of partial refresh.
The main question, why one costom property can work with repEntry, but other can't?
The answer comes down to when the property gets calculated. Compute it and add a print statement in the SSJS code and you'll see. IDs need to be calculated when the components get loaded, so at the earliest part of the processing. And most importantly this is when it's generating a single abstract set of components, not associated to a particular row entry, because it's not yet built the collection. Think of it like creating an abstract class before creating objects from it.

Can't get in line edited row in Xpages Dojo Data Grid to Save

I have created an enhanced Dojo Data Grid in an Xpages App. No I want to add an editable column. I get conflicting info on whether you can do this with viewJsonService or if you must use a viewItemFileService. I can't get either way to work. Would prefer to use Json, as everything that I need to do in this code works in Json, but I cannot even get any data to appear with the FileService. I understand to get the Json to work you need to have a site document set up and allow a "GET."
My code for the viewJsonService is below:
<xp:panel style="width:885.0px;height:300px">
<xe:restService pathInfo="gridData" id="restService1"
jsId="restServiceID">
<xe:this.service>
<xe:viewJsonService viewName="(dbAllRspPCTasks)"
var="rstEntry" systemColumns="4">
<xe:this.columns>
<xe:restViewColumn name="ID">
<xe:this.value><![CDATA[#{javascript:return rstEntry.getColumnValue("ID")}]]></xe:this.value>
</xe:restViewColumn>
<xe:restViewColumn name="status">
<xe:this.value><![CDATA[#{javascript:return rstEntry.getColumnValue("status")}]]></xe:this.value>
</xe:restViewColumn>
<xe:restViewColumn name="category">
<xe:this.value><![CDATA[#{javascript:return rstEntry.getColumnValue("category")}]]></xe:this.value>
</xe:restViewColumn>
<xe:restViewColumn name="title">
<xe:this.value><![CDATA[#{javascript:return rstEntry.getColumnValue("title")}]]></xe:this.value>
</xe:restViewColumn>
<xe:restViewColumn name="notes">
<xe:this.value><![CDATA[#{javascript:return rstEntry.getColumnValue("notes")}]]></xe:this.value>
</xe:restViewColumn>
</xe:this.columns>
<xe:this.keys><![CDATA[#{javascript:return viewScope.get("ID");
}]]></xe:this.keys>
</xe:viewJsonService>
</xe:this.service>
</xe:restService>
<xp:button value="Save" id="button4" style="font-weight:bold;font-size:10pt">
<xp:eventHandler event="onclick" submit="true" refreshMode="norefresh">
<xp:this.script><![CDATA[restServiceID.save();]]></xp:this.script>
</xp:eventHandler>
</xp:button>
<xe:djxDataGrid id="djxDataGrid1"
storeComponentId="restService1" initialWidth="100%"
rowSelector="25px" rowsPerPage="100"
dojoType="dojox.grid.EnhancedGrid" autoHeight="10">
<xe:djxDataGridColumn id="djxDataGridColumn1"
field="category" label="Category">
</xe:djxDataGridColumn>
<xe:this.dojoAttributes>
<xp:dojoAttribute name="autoWidth"
value="true">
</xp:dojoAttribute>
<xp:dojoAttribute name="canSort"
value="false">
</xp:dojoAttribute>
</xe:this.dojoAttributes>
<xe:this.errorMessage><![CDATA["Sorry...error loading tasks"]]></xe:this.errorMessage>
<xe:djxDataGridColumn id="djxDataGridColumn2"
field="status" formatter="displayIcon" width="25px" label="Sts">
</xe:djxDataGridColumn>
<xe:djxDataGridColumn id="djxDataGridColumn3"
label="Task" field="title" width="300px">
</xe:djxDataGridColumn>
<xe:djxDataGridColumn id="djxDataGridColumn4"
label="Notes..." field="notes" width="auto" editable="true">
</xe:djxDataGridColumn>
<xp:eventHandler event="onFocus" submit="false">
<xe:this.script><![CDATA[dijit.byId('#{id:djxDataGrid1}').canSort = function(col){
return false;
};]]></xe:this.script>
</xp:eventHandler>
</xe:djxDataGrid>
</xp:panel>
Per, OK on a test server I created a Web Site Document and checked PUT in the allowed methods and rebooted the server.
When I check
http:///api/data
I get a
{
"code":403,
"text":"Forbidden"
}
and I do not know why. What are some things that I should look for to ensure that I can enable a put?
Bryan

xpages number converter with combobox in ND9

I'm having trouble using number conversion with numberConvert in a combo box in xpages on a Domino 9 server. This used to work on the 8.5 server.
When I submit the values I get: Validation Error: Value is not valid
I also tried to populate the values with "new javax.faces.model.SelectItem" but that didn't make any difference.
Does anyone know how to use numbers in combo boxes in ND9?
Here is the source (I removed everything unneccesary for this example):
<xp:comboBox id="combo" value="#{viewScope.testfield}">
<xp:this.converter>
<xp:convertNumber type="number"></xp:convertNumber>
</xp:this.converter>
<xp:selectItem itemLabel="9" id="selectItem1" itemValue="9">
</xp:selectItem>
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var arr=new Array("0","1","2"); return arr;}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
<xp:message id="message1" for="combo"></xp:message>
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:save></xp:save>
</xp:this.action>
</xp:eventHandler>
</xp:button>
Please ensure that field 'testField' is of type 'Number' on the underlying form.
I had the same issue on 8.5.3 server. So, i wrote the below code to overcome the issue..
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:
var arr = ['0','1','2']
var comboOptions = [];
for (i = 0; i < arr.length; i++){
comboOptions.push(new javax.faces.model.SelectItem(parseFloat(arr[i]), arr[i]))
}
return comboOptions}]]>
</xp:this.value>
</xp:selectItems>
You can simplify the above code, if you know how to use managed beans.
Below is the code for bean.
public class ApplicationSettings implements Serializable{
private static final long serialVersionUID = 1L;
private List comboOptions;
public ApplicationSettings(){
loadDefaults();
}
public void loadDefaults(){
for(int x = 0; x <= 3; x = x+1){
SelectItem item = new SelectItem(new Double(x),""+x);
comboOptions.add(item);
}
}
public List getComboOptions() {
return comboOptions;
}
public void setComboOptions(List comboOptions) {
this.comboOptions = comboOptions;
}
}
In faces-configxml, register the managed bean(name: ApplicationSettings, scope:application).
Then in your xpage..
<xp:selectItems value="#{ApplicationSettings.comboOptions}"></xp:selectItems>
EDIT:
If you want to select numbers in a ComboBox you have to define comboBox's possible values as an array of numbers, not strings.
<xp:this.beforePageLoad><![CDATA[#{javascript:viewScope.testfield = 1}]]></xp:this.beforePageLoad>
<xp:comboBox id="combo" value="#{testfield}">
<xp:selectItem itemLabel="0" itemValue="${javascript:0}"></xp:selectItem>
<xp:selectItem itemLabel="1" itemValue="${javascript:1}"></xp:selectItem>
<xp:selectItem itemLabel="2" itemValue="${javascript:2}"></xp:selectItem>
</xp:comboBox>
This example works perfect without using a converter if the value is a scope variable.
If you have a flexible number of entries you can use both ways shown in Adibabu Kancharla's answer.
The number converter is necessary for binding to a document's number field. The following example works for me in ND853 and ND9. I had to add integerOnly="true" though:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.data>
<xp:dominoDocument var="document1" formName="NumberTest"
action="editDocument"
documentId="477FF8697EE50EDBC1257B710073DDE3">
</xp:dominoDocument>
</xp:this.data>
<xp:comboBox id="combo" value="#{document1.Number}">
<xp:selectItem itemLabel="0" itemValue="${javascript:0}"></xp:selectItem>
<xp:selectItem itemLabel="1" itemValue="${javascript:1}"></xp:selectItem>
<xp:selectItem itemLabel="2" itemValue="${javascript:2}"></xp:selectItem>
<xp:this.converter>
<xp:convertNumber type="number" integerOnly="true"></xp:convertNumber>
</xp:this.converter>
</xp:comboBox>
<xp:message id="message1" for="combo"></xp:message>
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:save></xp:save>
</xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:view>

XPages xe:listView won't hide the columns

I created a sample to demonstrate. I have a view called "testView" with three columns referencing "field1", "field2", "field3".
When I run this XPage all three columns in the display when it should not show the third column. Clicking the button does not hide the second column either.
Can anyone tell me what I have wrong?
<?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">
<xp:this.beforePageLoad><![CDATA[#{javascript:if ( sessionScope.showCol2 == null )
sessionScope.showCol2 = true;}]]></xp:this.beforePageLoad>
<xe:restService id="restService1">
<xe:this.service>
<xe:viewJsonService viewName="testView"
defaultColumns="true">
</xe:viewJsonService>
</xe:this.service>
</xe:restService>
<xp:panel style="margin-left:20.0px;margin-top:20.0px">
<xe:listView id="listView1" storeComponentId="restService1">
<xe:listViewColumn id="listViewColumn1" columnName="field1"
columnTitle="Field1">
</xe:listViewColumn>
<xe:listViewColumn id="listViewColumn2" columnName="field2"
columnTitle="Field2">
<xe:this.rendered><![CDATA[#{javascript:return sessionScope.showCol2;
}]]></xe:this.rendered></xe:listViewColumn>
<xe:listViewColumn id="listViewColumn3" columnName="field3"
columnTitle="Field3" rendered="false">
</xe:listViewColumn>
</xe:listView></xp:panel>
<xp:panel style="margin-top:20.0px;margin-left:20.0px">
<xp:button id="button1" value="Toggle Column 2">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="listView1">
<xp:this.action><![CDATA[#{javascript:if ( sessionScope.showCol2 == false ) {
sessionScope.showCol2 = true;
}
else {
sessionScope.showCol2 = false;
}}]]></xp:this.action>
</xp:eventHandler></xp:button>
</xp:panel></xp:view>
Looks like a bug in ExtLib. But you can hide the column in your code with hidden* property:
<xp:button id="button1" value="Toggle Column 2">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="listView1">
<xp:this.action>
<![CDATA[#{javascript:
var cmp = getComponent('listViewColumn2');
if( cmp.isHidden() ){
cmp.setHidden(false);
}else{
cmp.setHidden(true);
}
}]]>
</xp:this.action>
</xp:eventHandler>
</xp:button>
*: the property is hidden too

Resources