Editing documents in Domino without using a form or an agent
Category show-n-tell thursday
I guess this is an unplanned part two of an earlier SnTT. Judging from the 448 hits that one's gotten so far, there's apparently a bit of interest in being able to write to Domino databases without having to rely only on the standard design elements. Although pleased at being able to create new documents using this approach, however, I was reminded of Jake's post back in March expressing frustration at being able to easily AJAXify the editing of existing documents when I wrote my little instant messaging client the other night. I experienced the same frustration, because I wanted documents to disappear from the messages view once they'd been delivered; ideally, I thought, they should have a status field that defaults to "Pending" and is set upon delivery to "Delivered" to prevent them from being added over and over to the same chat window. I guess I wasn't thinking clearly, because the best I could come up with at the time was to force them to be deleted once delivered. This accomplished the primary goal but, again, not my preferred approach.
Then it occurred to me tonight, if we can create documents by posting data to the form's action URL, why can't we edit them the same exact way? Well, hoo-rah, we can.
First, I added a Status field to the Message form with a default value of "Pending". As I mentioned previously, posting to a form doesn't require all fields to be given a value, because any that are skipped simply evaluate to their default value. As it turns out, the same applies to editing: you don't have to remind Domino what all of the existing fields' values are; just tell it which fields are being modified and what the new values are.
Next, I added a view called "UNID" that just sorts ascending by @Text(@DocumentUniqueID), and a new property to my Chat object:
editDocumentUrlBase : "http://" + strServerName + "/" + strDbPath + "/UNID/",
For what it's worth, I'm using a Domino page element to store my JavaScript, since I can specify its MIME type in the element properties, and it allows me to use computed text to set certain variables (i.e. strServerName is populated via @GetHTTPHeader("HOST") and strDbPath is just @WebDbName). Much easier than using a standard script library and trying to extract these variables from the URL manually.
Finally, I added a new method to the Chat object:
updateMessageStatus : function (p_strUNID, p_strNewStatus) {
var editDocumentUrl = Chat.editDocumentUrlBase + p_strUNID + "?EditDocument&Seq=1";
new Ajax.Request(editDocumentUrl, {
method: 'post',
postBody: '__Click=0&Status=' + p_strNewStatus,
onComplete: null
});
}
As you can see, very similar to the previous approach - the only significant difference being the target URL. The key, though, seems to be the "Seq=1" portion. Similar to __Click, this is a factor in informing Domino that the document is being saved, not refreshed. This method having been added, I can now easily update the status of a message once it's delivered instead of just blowing it away:
Chat.updateMessageStatus(message.id, "Delivered");
Mission accomplished. But now I have a choice: do I create a new view to store only messages with a status of "Pending" and point Chat.checkMessageReception to that view instead? Nah...... too many views kill performance, and the whole reason I'm taking this approach is because I don't want any agents causing performance issues. Thankfully, the existing view is already set to display the documents in JSON syntax, so I simply updated the view (and the page that embeds it) to include the status in the data it returns, and added that evaluation to the existing if statement that determines whether a valid new message has been received:
if (message.content != "" && message.status == "Pending") {
Granted, sooner or later we'd want that view cleared out anyway or things would still get bogged down because it has to ignore all the messages it's already delivered. But the point is that we now have proof that documents can not only be created, but edited as well, via AJAX in a Domino application that contains no agents whatsoever. Huzzah.
I guess this is an unplanned part two of an earlier SnTT. Judging from the 448 hits that one's gotten so far, there's apparently a bit of interest in being able to write to Domino databases without having to rely only on the standard design elements. Although pleased at being able to create new documents using this approach, however, I was reminded of Jake's post back in March expressing frustration at being able to easily AJAXify the editing of existing documents when I wrote my little instant messaging client the other night. I experienced the same frustration, because I wanted documents to disappear from the messages view once they'd been delivered; ideally, I thought, they should have a status field that defaults to "Pending" and is set upon delivery to "Delivered" to prevent them from being added over and over to the same chat window. I guess I wasn't thinking clearly, because the best I could come up with at the time was to force them to be deleted once delivered. This accomplished the primary goal but, again, not my preferred approach.
Then it occurred to me tonight, if we can create documents by posting data to the form's action URL, why can't we edit them the same exact way? Well, hoo-rah, we can.
First, I added a Status field to the Message form with a default value of "Pending". As I mentioned previously, posting to a form doesn't require all fields to be given a value, because any that are skipped simply evaluate to their default value. As it turns out, the same applies to editing: you don't have to remind Domino what all of the existing fields' values are; just tell it which fields are being modified and what the new values are.
Next, I added a view called "UNID" that just sorts ascending by @Text(@DocumentUniqueID), and a new property to my Chat object:
editDocumentUrlBase : "http://" + strServerName + "/" + strDbPath + "/UNID/",
For what it's worth, I'm using a Domino page element to store my JavaScript, since I can specify its MIME type in the element properties, and it allows me to use computed text to set certain variables (i.e. strServerName is populated via @GetHTTPHeader("HOST") and strDbPath is just @WebDbName). Much easier than using a standard script library and trying to extract these variables from the URL manually.
Finally, I added a new method to the Chat object:
updateMessageStatus : function (p_strUNID, p_strNewStatus) {
var editDocumentUrl = Chat.editDocumentUrlBase + p_strUNID + "?EditDocument&Seq=1";
new Ajax.Request(editDocumentUrl, {
method: 'post',
postBody: '__Click=0&Status=' + p_strNewStatus,
onComplete: null
});
}
As you can see, very similar to the previous approach - the only significant difference being the target URL. The key, though, seems to be the "Seq=1" portion. Similar to __Click, this is a factor in informing Domino that the document is being saved, not refreshed. This method having been added, I can now easily update the status of a message once it's delivered instead of just blowing it away:
Chat.updateMessageStatus(message.id, "Delivered");
Mission accomplished. But now I have a choice: do I create a new view to store only messages with a status of "Pending" and point Chat.checkMessageReception to that view instead? Nah...... too many views kill performance, and the whole reason I'm taking this approach is because I don't want any agents causing performance issues. Thankfully, the existing view is already set to display the documents in JSON syntax, so I simply updated the view (and the page that embeds it) to include the status in the data it returns, and added that evaluation to the existing if statement that determines whether a valid new message has been received:
if (message.content != "" && message.status == "Pending") {
Granted, sooner or later we'd want that view cleared out anyway or things would still get bogged down because it has to ignore all the messages it's already delivered. But the point is that we now have proof that documents can not only be created, but edited as well, via AJAX in a Domino application that contains no agents whatsoever. Huzzah.







