I've been digging into Bootstrap for a bit now. One of the useful components is the progress bar. David Leedy did a great NotesIn9 on them and I followed it, and it was greatly valuable. I took his work and made a sample database. This is all his work, I just transcribed it (I changed the viewScope variable names however). Hopefully having this in a sample database will be useful.
Download the file
Cheers,
Brian
Wednesday, August 12, 2015
Tuesday, July 14, 2015
dataTable column width
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
<xp:column
id="column4"
style="width:5.0%">
so that was easy.
Cheers,
Brian
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>
Friday, June 26, 2015
Populate an InputText Date field (that has a calendar picker)
I didn't see much on this, so I'm posting in case it helps someone.
I'm working on an application that has an XPage that a user fills out, then clicks to get a new version of that page. Most of the data should carry over, including an inputText field for a Domino document bound to a date field and I have the default datepicker on it.
I put the values from the first page into sessionScopes and used that to populate them for the next page. Easier on the user. All of them worked except the date.
Here is what worked.
Getting the value:
var nDT:NotesDateTime = document1.getItemValueDateTime('EventDate');
sessionScope.put("EventDate", nDT.getDateOnly());
Setting the value in afterPageLoad:
document1.replaceItemValue('EventDate', session.createDateTime(sessionScope.EventDate));
I've not found a way to set the component value yet, it's just not worked in any permutation I've tried so far. This does what I need so far, so I stopped trying on the component.
Cheers,
Brian
I'm working on an application that has an XPage that a user fills out, then clicks to get a new version of that page. Most of the data should carry over, including an inputText field for a Domino document bound to a date field and I have the default datepicker on it.
I put the values from the first page into sessionScopes and used that to populate them for the next page. Easier on the user. All of them worked except the date.
Here is what worked.
Getting the value:
var nDT:NotesDateTime = document1.getItemValueDateTime('EventDate');
sessionScope.put("EventDate", nDT.getDateOnly());
Setting the value in afterPageLoad:
document1.replaceItemValue('EventDate', session.createDateTime(sessionScope.EventDate));
I've not found a way to set the component value yet, it's just not worked in any permutation I've tried so far. This does what I need so far, so I stopped trying on the component.
Cheers,
Brian
Wednesday, June 10, 2015
Looking for Domino/XPages Developer positions
My employer had decided to migration off the Domino platform. The direction chosen is not one I'm comfortable with, and so we have decided to part ways. They are doing no new development, and there will be limited allowance for changes to the existing .nsfs. I'm sad to have to go from what otherwise has been a great position, but where they are going is the one I don't want to go.
So, this puts me open. I'm up for contract or perm situations. I've been hitting the boards, but if you have a suggestion, please contact me at my yahoo.com address: brian.moore100 I've got quite a bit of experience, and I can bring that to work for you.
Cheers,
Brian
So, this puts me open. I'm up for contract or perm situations. I've been hitting the boards, but if you have a suggestion, please contact me at my yahoo.com address: brian.moore100 I've got quite a bit of experience, and I can bring that to work for you.
Cheers,
Brian
Subscribe to:
Posts (Atom)