Sorry if this is a super-basic question, but I haven't been doing this very long and I don't have a lot of resources available. Flying a bit blind here. Anyway...
We have an anti-coag form that was created by a third party years ago, before my time. There's a button on this form that populates fourteen fields on the form via this function:
{fn PrevDailyDoseWk1(){
obsnow("SUNDAY DOSE",last_signed_obs_value("SUNDAY DOSE")) +
chkdate("SUNDAY DOSE","COUMPILL7")+
obsnow("MONDAY DOSE",last_signed_obs_value("MONDAY DOSE")) +
chkdate("MONDAY DOSE","COUMPILL1") +
obsnow("TUESDAY DOSE",last_signed_obs_value("TUESDAY DOSE")) +
chkdate("TUESDAY DOSE","COUMPILL2") +
obsnow("WEDS. DOSE",last_signed_obs_value("WEDS. DOSE")) +
chkdate("WEDS. DOSE","COUMPILL3") +
obsnow("THURS. DOSE",last_signed_obs_value("THURS. DOSE")) +
chkdate("THURS. DOSE","COUMPILL4") +
obsnow("FRIDAY DOSE",last_signed_obs_value("FRIDAY DOSE")) +
chkdate("FRIDAY DOSE","COUMPILL5") +
obsnow("SAT. DOSE",last_signed_obs_value("SAT. DOSE")) +
chkdate("SAT. DOSE","COUMPILL6")
document.nochange1 = "yes"
}
}
When that function is called, it triggers every watcher expression on the form (73 in total, based on what I can see in the MEL trace) fourteen times. So the fields that are being populated fill in very... slowly... one... by... one... instead of simply filling in at once. Our users are getting quite irritated by it. Is there something I can do to that function so that the fields all get updated at once, and then the watcher expressions all update?
In case the question arises, this is chkdate():
{fn chkDate(a,b){
if durationdays(last_signed_obs_date(a),last_signed_obs_date(b))==0 then obsnow(b,last_signed_obs_value(b)) else "" endif
}
}
I would have attached the MEL trace, but I get an "Access Denied" message so I must not be awesome enough.
From the Creating Clinical Content document (emphasis added):
About watchers and triggers Trigger: An event that causes an expression to be evaluated The Centricity form system supports the notion of triggers for causing watcher expressions to be reevaluated. Observations and temporary document variables both trigger watcher expressions but function somewhat differently.
? Temporary (document) variables. If the variable changes, all watcher expressions that refer to that temporary variable are re-evaluated.
? Observations. If one observation changes, all watcher expressions that reference any observation are re-evaluated.
You would need to update the watcher functions and put some sort of test as to whether or not they needed to execute again. Say a function uses PROB_AFTER. You set a variable to the size of PROB_AFTER and the next time it runs, you compare the previous size to the current size and if they are the same, exit the function. Or, set a document variable in the button function first thing, and your other functions look for the existence of that variable and "abort" their run if they see it. Your button function would need to clear that variable after the function finishes or your watchers would never run again after your button push.
Thank you for your feedback, David. I can't even find the watcher functions this is triggering (they're not in the code exposed by VFE) so I'm thinking this is beyond my skill set. The users will have to live with the delay until we can get the original developer to look at it. Thanks again for the response.
David,
Do you think this technique will prevent the functions from firing multiple times ?
fn PrevDailyDoseWk1(){
if DOCUMENT.isBusy1=="" then
DOCUMENT.isBusy1 = "1"
else
return ""
endif
[Body of function code]
DOCUMENT.isBusy1 = ""
return ""
}{!DOCUMENT.isBusy1}
{fn chkDate(a,b){
if DOCUMENT.isBusy2=="" then
DOCUMENT.isBusy2 = "1"
else
return ""
endif
if durationdays(last_signed_obs_date(a),last_signed_obs_date(b))==0 then
obsnow(b,last_signed_obs_value(b))
else "" endif
DOCUMENT.isBusy2 = ""
return ""
}}{!DOCUMENT.isBusy2}
This sort of coding makes me very nervious though, but I was curious if this would prevent the extra calls to these functions, but retain the original intention of the code.
Ron, If you try it - I would like to know if this works for you.
- Beverly
This looks good:
fn PrevDailyDoseWk1(){
if DOCUMENT.isBusy1=="" then
DOCUMENT.isBusy1 = "1"
else
return ""
endif
[Body of function code]
DOCUMENT.isBusy1 = ""
return ""
}
I think that would be all you need. You might need the {!DOCUMENT.isBusy1} but I don't know for sure.
And then you would update each watcher code block like this:
{
if DOCUMENT.isBusy1 == "1" then
""
else
watcher code here
endif
}
That being said - this might not work. It all depends on timing. If the function changes DOCUMENT.isBusy1 to 1 and then back to blank before the watchers trigger, it won't work. Just depends on how the engine runs things. You might just do a quick form with just the button and its updated function and one or two updated watcher functions and trace it and see if the watchers execute when you press the button.
Good luck!
I ran into this issue with a form. We changed most of the fields from obsterms to document variables, and used a button (and if that did not get pushed, a page close handler function) to populate the obsterms with the final values from the document variables... was a lot of coding to changeover the form - ugh!