Hello All,
I'm wondering has anyone come up with any solutions for improving performance on forms with many obs? For example I have a form with about 60 terms. I would use document variables but one of the requirements is that I can recall the data from past visits. Given the large number of obs, when I enter a value in any one of them I can see the form ui refreshing as it checks every other obs term. This slows down data input. Has anyone found a way to code around this with MEL?
Thanks,
Brad
I am also interested in this. There has been a noticeable delay in some of our larger forms that wasn't there prior to 9.8 (along with the rest of CEMR). First thing I did was take all the print translation out, which helped slightly. I then went through to cut down junk code and always try to do a re-import after an upgrade, the re-imports seem to help slightly.
I usually create a load and save function for forms that need to be reloaded with a bunch of obs terms. The idea is to put all of your fields in as few obsterms as possible concatenated by `, ~, ^, or | (your choice).
EDIT: If you will be using this obsterm with LIST_OBS, you will want to avoid caret (^) and pipe (|) because those are used in LIST_OBS as delimiters.
Then you have a watcher function that creates these obsterms as they fill out the form. Set your obsterms like this:
{OBSNOW("OBS_TERM", DOCUMENT.VAR1 + "^" + DOCUMENT.VAR2 + "^" + DOCUMENT.VAR3)}
Just keep in mind that you only have 2000 characters of space available in the obs terms, so you need to account for overflow. I'm not sure what kind of data you are putting in your 60 fields, but you may be able to use 3 obs terms for this (20 in each).
It is important that you have ^ in between each document variable even if it is blank, because we will be parsing this out to refill the form on the next visit.
On the next visit when you are ready to load the variables with previous information, you just need to have a button (or you could do it once as soon as the form loads up for the first time) to call the load function.
{!fn LoadVariables()
{
if (OBSPREV("OBS_TERM") <> "") then
local var_arr = getfield(OBSPREV("OBS_TERM"), "^", "")
if size(var_arr) == 3 then //change 3 to be 60 or however many you put in this obsterm
DOCUMENT.VAR1 = var_arr[1]
DOCUMENT.VAR2 = var_arr[2]
DOCUMENT.VAR3 = var_arr[3]
endif
endif
}}
Since I moved our group to HTML forms, I haven't had to do this technique in a while. The good thing about HTML forms is that you control when things are evaluated instead of relying on inefficient watcher functions.
Mike, thanks for the suggestion. That makes sense to me and I'm going to give it a try.
I have taken a slightly different approach, I use another function to mask the fact that I am using obsterms, it keeps them all from firing constantly. You could also call a function when the form first opens to populate your data, and use document variables with this approach. You would use it the same way you use OBSNOW(). Note: I thought it was faster to rewrite this than find the one I actually use so watch for typos.
{fn MaskObs(){
cond
case (getnargs() == 3)
obsnow(getarg(1),getarg(2),getarg(3))
return getarg(2)
case (getnargs() == 2)
obsnow(getarg(1),getarg(2))
return getarg(2)
case (getnargs() == 1)
return obsnow(getarg(1))
endcond
return ""
}
}
I too use form load to move obs terms into document variables. Getting out of the form is somewhat more of an issue as there is no fool proof way of executing page close handler routines. This requires checking that the page close handler routine was executed in a form that the user must enter after the form in question is exited to ensure that the document variable repopulate the obs terms. The alternative is watcher functions for the document variables within the form that repopulate the obs term. The use of document variables is messy no matter how you time it.
Recently I noted that if the form was not visible, e.g. in a tab under the first tab, since there is no update obs terms on the visible form via the UI, the initialization is much faster. On a form without tabs, I plan to create a visibility segment that is not True until all variable have been initialized. Haven't tried it yet, but anxious to find out if it really works.