If you’re looking for a quick way to manipulate the data returned by a view data source, you can use URL parameters that match the property names. This allows you to effectively compute them without having to write code to compute the parameters. In this post, I’ll show several examples.
In my sample database, I have a categorized view in the Notes client.
I added a data source for this view to an XPages and dragged all of the columns on to the page to have it automatically create a view
Here’s the data source tag on the page — there are no computed properties.
<xp:this.data> <xp:dominoView var="view1" viewName="People"></xp:dominoView> </xp:this.data>
Using URL Parameters to Filter the View
To filter the view, all you have to do is append URL parameters with the same name as a filtering property of the view data source.
To limit the data to a single category, add a
To execute a full-text search, add a
search parameter. (The database must be full-text indexed or it will throw an error.) You can also include wildcards in the search parameter.
To filter the results based on the first sorted column in the view, use the
To set the view’s starting point, you can use the
startKeys parameter. (Note: The view will continue on to the end after the starting point.)
To expand or collapse categories in the view, use the
These attributes work on the view data source and not specifically on the view panel, so it is useful on a repeat control or any other control that uses a view data source.
If your data source has
ignoreRequestParameters set to true, then this will not work because it will – um – ignore the request parameters.
If you enter a parameter that doesn’t correspond exactly to a property name, then it will be ignored by the view data source.
You’re no doubt used to seeing URLs to open a document that look like this:
http://www.server.com/db.nsf/myPage.xsp?action=openDocument&documentId=0123456789ABCDEF0123456789ABCDEF in XPages. The
action URL parameters are used by each document data source by default. In this post, I’ll show how you can use the
requestParamPrefix property to define a separate set of URL parameters for an additional data source.
By default, a document data source will use the
action parameters to determine the document to open and the edit mode. However, if you have more than one document data source on a page, this may not be the behavior that you want.
For example, I have a database with a simple XPage that has two document data sources for the Person form.
<xp:dominoDocument var="document1" formName="Person" action="openDocument"> </xp:dominoDocument> <xp:dominoDocument var="document2" formName="Person" action="openDocument"> </xp:dominoDocument>
If I open the page with a standard URL, both display the same document.
If I change the
action parameter to
editDocument, then both change to edit mode. Sounds like a great way to generate a save conflict!
Of course, this isn’t really what I want. One option to work around this is to set the
ignoreRequestParams property of the document data source to
true and compute the
documentId property (and, optionally, the
This is the method that I am in the habit of using and it works well when putting the ID in a scope variable and using that for the computed property value.
ignoreReuqestParams property tells the data source to ignore the
action properties in the URL and leaves it up to you to manage them.
(Note: Even if you compute the
documentId, it will not matter if you don’t set
ignoreRequestParams to true; the URL parameters will still override the property value.)
However, there is another way to handle this situation without computing the data source properties — the
You can set this on a data source and it will look for a separate copy of the
action parameters and use them for that specific data source.
For example, if I set the
doc2_, then it will look for URL parameters named
doc2_action and use those for this data source.
You can add the parameter directly in the page source or find it in the properties panel under All Properties > data > data > [data source]. (This assumes the data source is at the page level. If it’s on a panel, then that would be your starting point to find the data source properties.)
Now, I can open two different documents on the same page with a URL like this:
With this approach, you do not need to set
true. In fact, if you do, then the URL parameters will be ignored — even if they contain the specified prefix.
Managing the Data Source with Scope Variables
I recently worked on an application that had a view of related documents embedded within a parent document page, along with an embedded form to work with the related documents. This concept applies to child/response documents as well as separate documents, related based on common piece of information. (By “embedded form”, I’m referring to a custom control with it’s own data source based on a separate Notes client form, displayed within the context of the parent page.)
As with any type of document data source, creating, viewing, and editing are the three types of data source actions.
By default, the embedded form is blank and can be used to submit a new related document. However, if the user clicks on a related document in the embedded view, they should have the ability to view or edit the selected document, based on their rights.
Along with the action, the document ID needs to be managed. It either needs to be blank (in the case of a new document) or set to the UNID of the document selected in the view.
The following steps were taken to implement this functionality:
- Compute the data source’s action from a scope variable (defaulting to createDocument if no other variable was specified)
- Compute the data source’s documentId from a scope variable
- Set the data source’s ignoreRequestParams attribute to true
- Set the links in the view to set the selected document’s UNID in a scope variable and also determine whether the form should be opened or edited and set the appropriate action in a scope variable (openDocument or editDocument, respectively)
- Set the links in the view to trigger a partial refresh on the form panel in order to update the document in the embedded form
- Set the Save button on the embedded form to clear the embedded form fields after saving a new or edited document
- Hope that no one would try to view and create documents within the same page view
The Biggest Challenge
The biggest challenge I ran into was creating a new document with the embedded form after viewing or editing an existing document. No matter what I did, it would always update the previously-edited document with any changes that were made.
Fortunately, I was able to solve that problem by scoping the data source to the request, so it stopped hanging onto the previous document and allowed for the creation of new documents. This was done via the scope property of the data source, found under All Properties > data > data > dominoDocument > scope.
Managing the Data Source Dynamically
This method works, manipulating the data source directly makes it much simpler to implement and manage! With a few lines of code, you can replace the need for computed data source values, leaving all of the logic in the link that opens the form.
In my case, I’m attaching the data source to a panel on the page. Sven’s snippet shows how to attach the data source to the page itself.
This response from Sven to a question on Stack Overflow shows how you can clear all data sources and add a new one (to work around the same problem I was facing). Note: If you do that, be sure to set the variable name of the new data source the same as when you first bound fields to it, so all field bindings remain in tact.
I did some testing and found that I didn’t even need to remove and re-create the data source. I’ve been testing just updating the parameters of the data source and it seems to work well. One caveat I’ve seen so far is that if I try to open a document in edit mode, close it, then re-open in read mode before changing the documentId of the source to another document, it sticks with the first mode. If you have a case where you need to do that in succession, then maybe removing the data source and re-creating it altogether would do the trick.
Now, I have a ‘New’ button at the top and a repeat control with links to open and edit each document.
var ds = getComponent('panelName').getData(); ds.setDocumentId(''); ds.setAction('createDocument');
Open Document (varRepeat is the repeat control variable)
var ds = getComponent('panelName').getData(); ds.setDocumentId(varRepeat.getDocument().getUniversalID().toString()); ds.setAction('openDocument');
Edit Document (varRepeat is the repeat control variable)
var ds = getComponent('panelName').getData(); ds.setDocumentId(varRepeat.getDocument().getUniversalID().toString()); ds.setAction('editDocument');
Two other things are required for this to work:
- The ignoreRequestParams property of the data source must be set to true, or the embedded form will pick up the id of the parent document from the URL. If you want to be sure it’s set properly, include this line: ds.setIgnoreRequestParams(true);
- Set the button or link to partially-refresh the panel that includes the embedded form and data source
This is much easier to maintain that all of the steps that the other method required.