As I noted in my prior post, our new XPages application will need links from Requisitions to all Purchase Orders that are created from that Requisition. Now, in regular old Notes, I’d handle this just by plopping down a single-category embedded view, using the Requisition’s ID to find just the right Purchase Orders. Since embedded views already allow you to open the document underneath, my work would be done.
Fortunately, having found that Server Side Javascript is not frightfully different from LotusScript. You already have the basic understanding of the document object model from doing LotusScript, so it’s just a matter of figuring out the syntax, right?
Since I want to display a set of links to the associated Purchase Orders, I decided the cleanest way to do that was using a Repeat Control. Unfortunately, knowing the tool I needed didn’t resolve the problem by itself.
First, I had to build the values that would go into my Repeat Control. I thought about binding the view here, but our data doesn’t reside in the same database as the XPage designs. That means I’d have to compute which database I needed and, so far, that felt beyond my talents. Fortunately, the wonderful folks over at Teamwork Solutions provided us with a quick way to get a handle to the database, a getDb function. So, rather than trying to figure out how to squeeze that into a binding, I stuck to my LotusScript roots and got a NotesDocumentCollection from the view.
<xp:this.value><![CDATA[#{javascript: var db:NotesDatabase = getDb("tamisDb"); var poView = db.getView("PObyProcReqDocID"); var docCollection = poView.getAllDocumentsByKey(getComponent("docID1").getValue()); return docCollection;}]]> </xp:this.value>
So, then, in my repeat, I can just refer to each document, pulling the values I want.
I always try to give my objects names that identify them clearly. My very first paid programming assignment was when I was pursuing my degree in Political Science, studying the Soviet Union. I worked at the National Superconducting Cyclotron Lab. It was a great place to work. Now, they don’t normally hire social studies majors to write code, but I hired in as a receptionist, then started working for the guys in Operations, walking around recording numbers on dials and checking on things. My boss knew I’d been a computer science major, so he guided me into re-writing their help document database. Every module in the database was named after a woman in his life. They were suitable names for him, because he knew the woman and the module names fit their personalities. I didn’t and I knew the next guy wouldn’t either, so I gave them all nice, functional names.
Why do I digress? Well, XPages is so eager to write code for you, that it assigns object names with object type and a number. I think a lot of people leave it that way, but when I’m in there, I need to assign names that fit. Sadly, I always end up with rowData as the object name for my repeats. I don’t know if changing from that had doomed my early repeats or if it’s just superstitious, but I leave it as rowData.
So, back to the completed code. Our ‘value’ section is there, identifying the NotesDocumentCollection we need, of all Purchase Orders documents that belong to the Requisition. For each one, we establish a link, labelling it by grabbing a field value, then using a Simple Action to open the pro_purchaseOrder XPage that displays Purchase Orders and using the UNID from the document selected as our rowData.
<xp:repeat id="purchaseOrderLinkRepeat" rows="30" var="rowData" repeatControls="false" removeRepeat="true"> <xp:this.value><![CDATA[#{javascript: var db:NotesDatabase = getDb("tamisDb"); var poView = db.getView("PObyProcReqDocID") var docCollection = poView.getAllDocumentsByKey(getComponent("docID1").getValue()); return docCollection;}]]> </xp:this.value> <xp:link id="poLink"> <xp:this.text><![CDATA[#{javascript:"Purchase record: " + rowData.getItemValueString("TSWFNumber");}]]> </xp:this.text> <xp:eventHandler event="onclick" submit="true" refreshMode="complete"> <xp:this.action> <xp:openPage name="/pro_purchaseOrder.xsp" target="openDocument" documentId="#{javascript:rowData.getUniversalID();}"> </xp:openPage> </xp:this.action> </xp:eventHandler> </xp:link> </xp:repeat>
Honestly, that little slice of code took me several days to get my head around. I wasn’t staring at the screen the whole time, but the stops-and-starts of trying one approach and then another were tremendous. Those hurdles truly point out that a seasoned developer might well accomplish in an hour what it takes a new developer (or one new to the language) an entire week to do. Now that I have it under my belt, my team and I will be reusing this all over the place. I hope you can as well.