Faking Computed For Display Fields
Imagine a Computed For Display (CFD) field that showed the result of @Now on a web page. Now imagine you submit the page and have the Web Query Save agent print back to the browser the value from this field. You might expect to see the same date/time value that had been displayed on the page. in fact you'd see the updated value of @Now, instead of @WhenIOpenedThisDocument. This is because computed fields get re-computed, once the form is submitted. Sometimes this isn't the desired behaviour and I've got a quick tip that might help.
Instead of using a computed field use a hidden editable field. Make the default value the same as you would any normal computed value. When you create the document from new this value is in effect computed for display. But normal editable fields never re-compute the value. To force it to re-compute each time we need to remove the field from the document each time it saves. This is easily done with the following line at the end of the document's WebQuerySave agent:
Call webDocument.RemoveItem("DocOpened")
So, it's just like a CFD field, in that it never actually saves with the document. Next time the document opens Domino gives it an updated value. Et voila!
But wait - there's one little gotcha involved. When I said the editable field was hidden I meant it was type="hidden" rather than actually being hidden from the browser. If you use Hide Whens the field is given its value at the time it's submitted. By having the browser send the field value to the server we can explicitly tell it exactly what value to use.
Where would this be useful? Well, I've used it in a solution to yesterday's scenario. When I open a document I want to log the time it was last modified. When it's submitted we can check this value with the one held in the back-end document. If they are different, there's a problem we need to deal with. I tried using the .LastModified property but found that didn't work. Instead I add a fake computed field, as described here, with a default value of @Modified.
The only drawback to this @Modified method is that it's only accurate to withing one second. There's an ever so small chance that two users could edit the document and these values still appear the same, but I can't get my head round the scenario required, so I can live with the risk. You can of course check more than simply this date. Maybe check the date and the name of the editor or the document's workflow status.
Expect an article talking about this. There's an interesting solution to a common problem in here somewhere. I just need to make the solution a little cleaner.
Hi Jake...
Why not use the "$Revisions" field along with your example. Domino uses is for the same purpose:
(i.e. Every document includes a $Revisions field that stores, by default, the date and time of each document editing session. Domino uses this field to resolve replication or save conflicts that occur when two users simultaneously edit the same document on one replica or edit the same document on different replicas between replications.)
You could use it by downloading the "$Revisions" when you open the form (can be the top 5.. should be enough). When you save the form, just pass the value you downloaded back to the server and use the value to check if any changes have been made!
Regards
Patrick
Nice idea Patrick. I'll have a play with that. Would be nice to tell the user "Joe Bloggs saved this document since you opened it..."
Be careful of $Revisions, i've tried to use this for the same purpose. For some strange reason (only known to Lotus) the $Revisions time stamp is always one edit behind i.e. the second last, not the most previous, edit time appears. There's a few postings about this on Notes.net.
Jake,
I did exactly what you are trying to do in a web app a year or so ago. I'll try to dig out the code tonight, but I think you're proceeding in the right direction. If my memory serves me right, it worked by comparing modified stamps on the backend document and one generated when the form was served out.
The trouble is my memory often doesn't serve me right, so I'll dig out the code. :-)
Arka
OK, here's how it worked ...
When the document is served, it is given a date-time stamp of @Now.
The WebQuerySave agent then compares this date-time stamp against the LastModified property of the existing backend document. If doc.LastModified > date-time stamp, you have a save conflict.
The date-time stamp was a computed-when-composed field effectively set to @Now. The WebQuerySave agent removed this field from the document prior to saving it.
This method of comparison was accurate to the nearest 1/100th of a second. I also didn't encounter any problems with the LastModified property. What problems did you hit?
Happy to provide some sample code if it helps - though I imagine you must have covered most of this by now.
Arka
Addendum:
"The date-time stamp was a computed-when-composed field effectively set to @Now." ... and that field was used as the value for a hidden INPUT on the web form.
What abt Savetodisk property?
Set item = doc.GetFirstItem("Temp")
item.SaveToDisk = False
Partha
How about:
1. Have a cumputed @now field and another date editable field.
2. In your save, use java script to copy ythe value from the computed field to the editable field.
My question is why use LotusScript when you could have everything reside within the field itself. The advantage with using LotusScript you could delete it under some conditions. But if you are looking to remove the field every time then you could but the following code in the 'Input Validation' event.
@if( @IsDocBeingSaved ; @DeleteField ; DocOpened )
Jake,
couldn't you use the 'readonly' argument?
Something like this: Create an input field with @Now formula as default value, but having the 'readonly' in the HTML Arguments.