In my last post, I'd say I'd look into controlling the column width. It's a setting:
<xp:column
id="column4"
style="width:5.0%">
so that was easy.
Cheers,
Brian
Tuesday, July 14, 2015
dataTable with Categories
I've been using DataTables for a number of things lately, where I need a bit more flexibility than a viewPanel, but I don't want to build it from scratch with a Repeat.
I'm currently working on process where I'm making a nsf to replace a MS Access database. So I'm having to adjust from the relational method. This means I need to use a key to look things up in a view to display the human friendly words rather than the code. So traditional Notes views don't do that. DataTables give me the flexibility I need. For part of this, I have 'events', and these will have one to several classes at each of these events. I want to hide the classes for each event until I click something to make it look neater and to save space.
DataTables don't have a native way to show categories, so I found one. I put a repeat in a column, and populate that repeat with a NotesViewEntryCollection from a value in a row of the DataTable. I tried to use the plus/minus icons like shown here in a great post by Ulrich Krause. But when I paged the icons disappeared. Both of them. So I used the basic idea, and put a link in that was always there to show the classes, and another link to hide them if desired. It works like I desire, so fine.
So this does what I wanted. I'm putting the code below. I have a few things to adjust. First, the classes should be in a table so they display better (I'm not putting it in to make the code a little shorter). Also, the columns resize when the repeat is expanded. Something I'll look into fixing after I post this.
Cheers,
Brian
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.data>
<xp:dominoView
var="view1"
viewName="Event\Name">
<xp:this.databaseName><![CDATA[#{javascript:var curServer = @Subset(@DbName(),1);
if(@Left(curServer.toLowerCase(), "/") == "cn=svrname") {
session.getDatabase('svrname/OU', 'foldername\\Data.nsf');
} else {
session.getDatabase('', 'foldername\\Data.nsf');
}}]]></xp:this.databaseName>
</xp:dominoView>
</xp:this.data>
<xp:dataTable
id="dataTable1"
rows="30"
var="rowData"
value="#{view1}">
<xp:this.facets>
<xp:pager
partialRefresh="true"
layout="Previous Group Next"
xp:key="header"
id="pager1">
</xp:pager>
<xp:pager
partialRefresh="true"
layout="Previous Group Next"
xp:key="footer"
id="pager2">
</xp:pager>
</xp:this.facets>
<xp:column id="column1">
<xp:this.facets>
<xp:label
value="Event Name"
id="label1"
xp:key="header">
</xp:label>
</xp:this.facets>
<xp:link
escape="true"
id="link1">
</xp:link>
<xp:text
escape="true"
id="computedField4">
<xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[0];}]]></xp:this.value></xp:text></xp:column>
<xp:column id="column2">
<xp:text
escape="true"
id="computedField5">
<xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[4];}]]></xp:this.value></xp:text>
<xp:this.facets>
<xp:label
value="Date"
id="label2"
xp:key="header">
</xp:label>
</xp:this.facets>
</xp:column>
<xp:column id="column3">
<xp:this.facets>
<xp:label
value="Group"
id="label3"
xp:key="header">
</xp:label>
</xp:this.facets>
<xp:text
escape="true"
id="computedField6">
<xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[3];}]]></xp:this.value></xp:text></xp:column>
<xp:column id="column4">
<xp:this.facets>
<xp:label
value="Number"
id="label4"
xp:key="header">
</xp:label>
</xp:this.facets>
<xp:text
escape="true"
id="computedField7">
<xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[2];}]]></xp:this.value>
<xp:this.converter>
<xp:convertNumber
type="number"
integerOnly="true">
</xp:convertNumber>
</xp:this.converter>
</xp:text></xp:column>
<xp:column id="column6">
<xp:panel id="mainpanel">
<xp:link
escape="true"
text="Classes"
id="link6">
<xp:eventHandler
event="onclick"
submit="false">
<xp:this.script><![CDATA[var visibility = 'show';
XSP.partialRefreshGet("#{id:mainpanel}", {
params: {'$$xspsubmitvalue': visibility},
onComplete: function () {
XSP.partialRefreshGet("#{id:secondpanel}", {
params: {'$$xspsubmitvalue': visibility}});}
});]]></xp:this.script>
</xp:eventHandler></xp:link>
</xp:panel></xp:column>
<xp:column id="column5">
<xp:this.facets>
<xp:label
value="Courses"
id="label5"
xp:key="header">
</xp:label>
</xp:this.facets>
<xp:panel id="secondpanel">
<xp:repeat
id="repeat1"
rows="30"
rendered="#{javascript:context.getSubmittedValue()== 'show'}"
var="rptRowData">
<xp:this.value><![CDATA[#{javascript:var curServer = @Subset(@DbName(),1);
if(@Left(curServer.toLowerCase(), "/") == "cn=svrname") {
var dataDb:NotesDatabase=session.getDatabase('svrname/ou', 'foldername\\Data.nsf');
} else {
var dataDb:NotesDatabase=session.getDatabase('', 'foldername\\Data.nsf');
}
var v:NotesView=dataDb.getView('Class Instance\\Event-Course');
var nvec:NotesViewEntryCollection=v.getAllEntriesByKey(rowData.getColumnValues()[2] + '', true);
return nvec;}]]></xp:this.value>
<xp:text
escape="true"
id="computedField1">
<xp:this.value><![CDATA[#{javascript:rptRowData.getColumnValues()[1];}]]></xp:this.value>
</xp:text>
   
<xp:text
escape="true"
id="computedField2">
<xp:this.value><![CDATA[#{javascript:rptRowData.getColumnValues()[2];}]]></xp:this.value>
<xp:this.converter>
<xp:convertNumber
type="number"
integerOnly="true">
</xp:convertNumber>
</xp:this.converter>
</xp:text>
      
<xp:text
escape="true"
id="computedField3">
<xp:this.value><![CDATA[#{javascript:var cNumV:NotesView=database.getView('Course Number');
var cNVE:NotesViewEntry=cNumV.getEntryByKey(rptRowData.getColumnValues()[1], true);
if(cNVE != null){
return cNVE.getColumnValues()[1];
}
return "Course Name not found";}]]></xp:this.value>
</xp:text>
      
</xp:repeat>
<xp:link
escape="true"
text="Close"
rendered="#{javascript:context.getSubmittedValue()== 'show'}"
id="link5">
<xp:eventHandler
event="onclick"
submit="false">
<xp:this.script><![CDATA[var visibility = 'hide';
XSP.partialRefreshGet("#{id:mainpanel}", {
params: {'$$xspsubmitvalue': visibility},
onComplete: function () {
XSP.partialRefreshGet("#{id:secondpanel}", {
params: {'$$xspsubmitvalue': visibility}});}
});]]></xp:this.script>
</xp:eventHandler>
</xp:link>
</xp:panel>
</xp:column>
</xp:dataTable>
<xp:br></xp:br>
</xp:view>
I'm currently working on process where I'm making a nsf to replace a MS Access database. So I'm having to adjust from the relational method. This means I need to use a key to look things up in a view to display the human friendly words rather than the code. So traditional Notes views don't do that. DataTables give me the flexibility I need. For part of this, I have 'events', and these will have one to several classes at each of these events. I want to hide the classes for each event until I click something to make it look neater and to save space.
DataTables don't have a native way to show categories, so I found one. I put a repeat in a column, and populate that repeat with a NotesViewEntryCollection from a value in a row of the DataTable. I tried to use the plus/minus icons like shown here in a great post by Ulrich Krause. But when I paged the icons disappeared. Both of them. So I used the basic idea, and put a link in that was always there to show the classes, and another link to hide them if desired. It works like I desire, so fine.
So this does what I wanted. I'm putting the code below. I have a few things to adjust. First, the classes should be in a table so they display better (I'm not putting it in to make the code a little shorter). Also, the columns resize when the repeat is expanded. Something I'll look into fixing after I post this.
Cheers,
Brian
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.data>
<xp:dominoView
var="view1"
viewName="Event\Name">
<xp:this.databaseName><![CDATA[#{javascript:var curServer = @Subset(@DbName(),1);
if(@Left(curServer.toLowerCase(), "/") == "cn=svrname") {
session.getDatabase('svrname/OU', 'foldername\\Data.nsf');
} else {
session.getDatabase('', 'foldername\\Data.nsf');
}}]]></xp:this.databaseName>
</xp:dominoView>
</xp:this.data>
<xp:dataTable
id="dataTable1"
rows="30"
var="rowData"
value="#{view1}">
<xp:this.facets>
<xp:pager
partialRefresh="true"
layout="Previous Group Next"
xp:key="header"
id="pager1">
</xp:pager>
<xp:pager
partialRefresh="true"
layout="Previous Group Next"
xp:key="footer"
id="pager2">
</xp:pager>
</xp:this.facets>
<xp:column id="column1">
<xp:this.facets>
<xp:label
value="Event Name"
id="label1"
xp:key="header">
</xp:label>
</xp:this.facets>
<xp:link
escape="true"
id="link1">
</xp:link>
<xp:text
escape="true"
id="computedField4">
<xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[0];}]]></xp:this.value></xp:text></xp:column>
<xp:column id="column2">
<xp:text
escape="true"
id="computedField5">
<xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[4];}]]></xp:this.value></xp:text>
<xp:this.facets>
<xp:label
value="Date"
id="label2"
xp:key="header">
</xp:label>
</xp:this.facets>
</xp:column>
<xp:column id="column3">
<xp:this.facets>
<xp:label
value="Group"
id="label3"
xp:key="header">
</xp:label>
</xp:this.facets>
<xp:text
escape="true"
id="computedField6">
<xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[3];}]]></xp:this.value></xp:text></xp:column>
<xp:column id="column4">
<xp:this.facets>
<xp:label
value="Number"
id="label4"
xp:key="header">
</xp:label>
</xp:this.facets>
<xp:text
escape="true"
id="computedField7">
<xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[2];}]]></xp:this.value>
<xp:this.converter>
<xp:convertNumber
type="number"
integerOnly="true">
</xp:convertNumber>
</xp:this.converter>
</xp:text></xp:column>
<xp:column id="column6">
<xp:panel id="mainpanel">
<xp:link
escape="true"
text="Classes"
id="link6">
<xp:eventHandler
event="onclick"
submit="false">
<xp:this.script><![CDATA[var visibility = 'show';
XSP.partialRefreshGet("#{id:mainpanel}", {
params: {'$$xspsubmitvalue': visibility},
onComplete: function () {
XSP.partialRefreshGet("#{id:secondpanel}", {
params: {'$$xspsubmitvalue': visibility}});}
});]]></xp:this.script>
</xp:eventHandler></xp:link>
</xp:panel></xp:column>
<xp:column id="column5">
<xp:this.facets>
<xp:label
value="Courses"
id="label5"
xp:key="header">
</xp:label>
</xp:this.facets>
<xp:panel id="secondpanel">
<xp:repeat
id="repeat1"
rows="30"
rendered="#{javascript:context.getSubmittedValue()== 'show'}"
var="rptRowData">
<xp:this.value><![CDATA[#{javascript:var curServer = @Subset(@DbName(),1);
if(@Left(curServer.toLowerCase(), "/") == "cn=svrname") {
var dataDb:NotesDatabase=session.getDatabase('svrname/ou', 'foldername\\Data.nsf');
} else {
var dataDb:NotesDatabase=session.getDatabase('', 'foldername\\Data.nsf');
}
var v:NotesView=dataDb.getView('Class Instance\\Event-Course');
var nvec:NotesViewEntryCollection=v.getAllEntriesByKey(rowData.getColumnValues()[2] + '', true);
return nvec;}]]></xp:this.value>
<xp:text
escape="true"
id="computedField1">
<xp:this.value><![CDATA[#{javascript:rptRowData.getColumnValues()[1];}]]></xp:this.value>
</xp:text>
   
<xp:text
escape="true"
id="computedField2">
<xp:this.value><![CDATA[#{javascript:rptRowData.getColumnValues()[2];}]]></xp:this.value>
<xp:this.converter>
<xp:convertNumber
type="number"
integerOnly="true">
</xp:convertNumber>
</xp:this.converter>
</xp:text>
      
<xp:text
escape="true"
id="computedField3">
<xp:this.value><![CDATA[#{javascript:var cNumV:NotesView=database.getView('Course Number');
var cNVE:NotesViewEntry=cNumV.getEntryByKey(rptRowData.getColumnValues()[1], true);
if(cNVE != null){
return cNVE.getColumnValues()[1];
}
return "Course Name not found";}]]></xp:this.value>
</xp:text>
      
</xp:repeat>
<xp:link
escape="true"
text="Close"
rendered="#{javascript:context.getSubmittedValue()== 'show'}"
id="link5">
<xp:eventHandler
event="onclick"
submit="false">
<xp:this.script><![CDATA[var visibility = 'hide';
XSP.partialRefreshGet("#{id:mainpanel}", {
params: {'$$xspsubmitvalue': visibility},
onComplete: function () {
XSP.partialRefreshGet("#{id:secondpanel}", {
params: {'$$xspsubmitvalue': visibility}});}
});]]></xp:this.script>
</xp:eventHandler>
</xp:link>
</xp:panel>
</xp:column>
</xp:dataTable>
<xp:br></xp:br>
</xp:view>
Saturday, July 4, 2015
StartKeys for categorized viewPanel and number column
In case this helps someone:
I have a database shared by a couple of departments, I use a field to segregate them. Each document has a MemberKey with a number value.
The first column is the department, sorted but not categorized, then a view were the column is sorted on numbers. As numbers they don't sort in the "proper" order. So I created a new column that padded it with zeroes to for the sort to be correct:
@Right("00000" + @Text(MemberKey);5)
So the third column is just the number, so it appears properly.
So I want this in an XPage viewPanel and to use the startKeys to get the the number desired.
I set the viewPanel to filter by the department name, and don't display the padded view. But it doesn't work. It doesn't work if I use the padded column either. It's because I'm getting just one category, so it's not really "starting" there.
I noticed the startKeys element can take a Vector, so I tried that. And it works.
I have a view panel that does not
I have a field where I populate a viewScope called vFilter. If that is null, it return just one element in the vector, the department. Otherwise it returns a two element vector, with the department and the number I want to go to.
Here is my code in the startKeys element. (I'm using part of Thomas Adrian's Intrapages).
var query = new java.util.Vector();
var v = database.getView("(LookupUsers)");
var userdoc:NotesDocument = v.getDocumentByKey("User_UNID_" + userid,true);
if(userdoc!=null){
query.add(userdoc.getItemValueString('regDepartment'));
} else {
query.add("Department not found");
}
if(viewScope.vFilter != null){
query.add(@Right('00000' + viewScope.vFilter,5));
return query;
}
return query;
Cheers,
Brian
I have a database shared by a couple of departments, I use a field to segregate them. Each document has a MemberKey with a number value.
The first column is the department, sorted but not categorized, then a view were the column is sorted on numbers. As numbers they don't sort in the "proper" order. So I created a new column that padded it with zeroes to for the sort to be correct:
@Right("00000" + @Text(MemberKey);5)
So the third column is just the number, so it appears properly.
So I want this in an XPage viewPanel and to use the startKeys to get the the number desired.
I set the viewPanel to filter by the department name, and don't display the padded view. But it doesn't work. It doesn't work if I use the padded column either. It's because I'm getting just one category, so it's not really "starting" there.
I noticed the startKeys element can take a Vector, so I tried that. And it works.
I have a view panel that does not
I have a field where I populate a viewScope called vFilter. If that is null, it return just one element in the vector, the department. Otherwise it returns a two element vector, with the department and the number I want to go to.
Here is my code in the startKeys element. (I'm using part of Thomas Adrian's Intrapages).
var query = new java.util.Vector();
var v = database.getView("(LookupUsers)");
var userdoc:NotesDocument = v.getDocumentByKey("User_UNID_" + userid,true);
if(userdoc!=null){
query.add(userdoc.getItemValueString('regDepartment'));
} else {
query.add("Department not found");
}
if(viewScope.vFilter != null){
query.add(@Right('00000' + viewScope.vFilter,5));
return query;
}
return query;
Cheers,
Brian
Wednesday, July 1, 2015
ComboBox - Validate so default value is not selected
One of the things that I've been trying to get to work in XPages is getting validation to reject the default value of a combobox. Well, this morning I sat down and decided to get it done. I've used other methods to get around this until now, but this seems to do it.
I have a combobox with "--Select--" as the default value. If that value is still there on submission, I want a display error control to execute. To do this, I think you need to have "--Select--" as the itemValue as well as the itemLabel, but I'm not sure, as I habitually use both anyway.
Add a validateContraint, and use the RegEx "^((?!--Select--).)*$" , I got this from this StackOverflow Post. So on submission, if a value hasn't been selected (errm, sorry) no dice.
I tested on a combobox that needed the user to select the month, the entire element is below.
There may be a better way, but having this will be a relief for me.
Cheers,
Brian
<xp:comboBox
id="comboBox1"
value="#{document1.rptCover}"
style="width:125.0px"
defaultValue="--Select--">
<xp:this.validators>
<xp:validateConstraint
regex="^((?!--Select--).)*$"
message="Select a month">
</xp:validateConstraint>
</xp:this.validators>
<xp:selectItem
itemLabel="--Select--"
id="selectItem15" itemValue="--Select--"/>
<xp:selectItem
itemLabel="January"
itemValue="January"
id="selectItem1" />
<xp:selectItem
itemLabel="February"
itemValue="February"
id="selectItem2" />
<xp:selectItem
itemLabel="March"
itemValue="March"
id="selectItem3" />
<xp:selectItem
itemLabel="April"
itemValue="April"
id="selectItem4" />
<xp:selectItem
itemLabel="May"
itemValue="May"
id="selectItem5" />
<xp:selectItem
itemLabel="June"
itemValue="June"
id="selectItem6" />
<xp:selectItem
itemLabel="July"
itemValue="July"
id="selectItem7" />
<xp:selectItem
itemLabel="August"
itemValue="August"
id="selectItem8" />
<xp:selectItem
itemLabel="September"
itemValue="September"
id="selectItem9" />
<xp:selectItem
itemLabel="October"
itemValue="October"
id="selectItem10" />
<xp:selectItem
itemLabel="November"
itemValue="November"
id="selectItem11" />
<xp:selectItem
itemLabel="December"
itemValue="December"
id="selectItem12" />
</xp:comboBox>
I have a combobox with "--Select--" as the default value. If that value is still there on submission, I want a display error control to execute. To do this, I think you need to have "--Select--" as the itemValue as well as the itemLabel, but I'm not sure, as I habitually use both anyway.
Add a validateContraint, and use the RegEx "^((?!--Select--).)*$" , I got this from this StackOverflow Post. So on submission, if a value hasn't been selected (errm, sorry) no dice.
I tested on a combobox that needed the user to select the month, the entire element is below.
There may be a better way, but having this will be a relief for me.
Cheers,
Brian
<xp:comboBox
id="comboBox1"
value="#{document1.rptCover}"
style="width:125.0px"
defaultValue="--Select--">
<xp:this.validators>
<xp:validateConstraint
regex="^((?!--Select--).)*$"
message="Select a month">
</xp:validateConstraint>
</xp:this.validators>
<xp:selectItem
itemLabel="--Select--"
id="selectItem15" itemValue="--Select--"/>
<xp:selectItem
itemLabel="January"
itemValue="January"
id="selectItem1" />
<xp:selectItem
itemLabel="February"
itemValue="February"
id="selectItem2" />
<xp:selectItem
itemLabel="March"
itemValue="March"
id="selectItem3" />
<xp:selectItem
itemLabel="April"
itemValue="April"
id="selectItem4" />
<xp:selectItem
itemLabel="May"
itemValue="May"
id="selectItem5" />
<xp:selectItem
itemLabel="June"
itemValue="June"
id="selectItem6" />
<xp:selectItem
itemLabel="July"
itemValue="July"
id="selectItem7" />
<xp:selectItem
itemLabel="August"
itemValue="August"
id="selectItem8" />
<xp:selectItem
itemLabel="September"
itemValue="September"
id="selectItem9" />
<xp:selectItem
itemLabel="October"
itemValue="October"
id="selectItem10" />
<xp:selectItem
itemLabel="November"
itemValue="November"
id="selectItem11" />
<xp:selectItem
itemLabel="December"
itemValue="December"
id="selectItem12" />
</xp:comboBox>
Subscribe to:
Posts (Atom)