Another question for everyone:
I'm trying to use a custom function in a text component. Basically, I want to make a text component that pulls in specific information from any order added during this update.
Here's what I have now:
{fmt("Orders", "B,2")}
{'{getOrders()}'}
{
fn getOrders() {
local tests = getfield(ORDERS_NEW("delimited",""),"|","")
local temp
local testrslt = ""
local refrslt = ""
local endrslt = ""
local i = 1
for i = 1, i <= size(tests), i = i + 1 do
temp = getfield(tests[i], "^","")
if DURATIONDAYS(temp[4], str(._TODAYSDATE)) < 182 then
testrslt = testrslt + temp[1] + ", " + temp[3] + " on " + temp[4] + HRET +
" - Diagnosis: " + temp[6] + " (" + temp[7] + ")" + HRET +
" - Autho Provider: " + temp[21] + HRET + HRET
else
""
endif
endfor
if testrslt <> "" then
testrslt = testrslt
else
testrslt = "No tests or referrals ordered in this update."
endif
}
}
I feel like this isn't actually something that you're supposed to do in a text component, because the behavior is really weird. If I start a new encounter and add an order, this text component pulls in the requested data.
If I put the document on hold and reopen it, it says:
{getOrders() <-FUNCTION DEFINITION IS NOT EXECUTABLE
If I add the component again, that error message will be replaced by the actual order data I want to display, but will duplicate it, because technically I added another component to the document. Oh, and sometimes it corrupts the document and CPS will crash every time it's clicked on. Obviously this isn't acceptable. Am I flying too close to the sun?
Initial thoughts:
1. why {'{getOrders()}'}, and not {GetOrders()}
2. if there are no new orders, then all heck breaks loose in your for loop and there indeed will be a crash, must check for no new orders, if tests<>"" then (execute your function) else return "No new orders" endif
3. You need to execute the function on every load, e.g. after hold, {! GetOrders()}
4. Text components are not my thing, there may be other issues I am unaware of.
5. Feel free to contact me directly.
Thanks for the leads.
1. Text Components are weird, because consistency isn't CPS' thing, apparently. In MEL forms (and maybe even in Histories), "!" will cause the function to run on form load, but in text components, you need the additional curly braces and single quotes, like {'{function()}'}. As to why I don't capitalize the first character, that's just how I learned to write camel case. Our library functions were written a long time ago, and those capitalize the first character, so the added benefit is it's easy to see what is in the form vs. what is in the library.
2. That's a good observation regarding not having any orders, but the way the actual code is working (and this may be a fluke) is that it fills the testrslt variable with nothing, so when it hits the if statement, the returned statement is "No tests or referrals ordered in this update.". This still defaults to the error message when the document is held and reopened.
3. I did try adding the bang to the beginning of the function as well, figuring doubling the checks on form load wouldn't hurt, but it still gave me the error message...
When working with text components, it is important to understand two key points:
1) When loading, the code is executed in a top down workflow. Using the Bam (!) will have no impact because it is a load/read once in the order it appears and done. This is unlike code in a form, as you seem to be aware of. In your example, the function call appears before the function definition. Reverse the order and you should be OK.
2) Text components are 'static code' in the update (not much different from text you type in the update directly). They can be referenced and executed on initial load, but for subsequent loads, they do not 're-execute' all of the code inside of them. Using the {'{fnNameHere()}'} syntax forces the desired code (in this case, a function call) into a different memory space that is normally reserved for encounter forms. In that space, it becomes a 'watcher' and is able to be executed in real time.
Hope this helps.
That's what I thought I understood about {'{function()}'}, but it's not working in real time. Do you know of any tricks to force it through or do you see something I'm doing wrong that is preventing it from updating continuously?
Did you move the function call below the function definition?
it should appear in this order:
{ fn getOrders() {
... function body
}
}
{fmt("Orders", "B,2")}
{'{getOrders()}'}
That didn't work... I now have the function itself above everything, including where it's called, but no luck.
Do you see a red '<value>' text in the chart note when the text component is inserted?
All the text, no matter the state, is red. Does that mean something? At least everything relating to the function is red. The {FMT("Orders", etc)} is black.
OK, at least we know it is 'working' properly from the watcher standpoint.
Now we need to address the 'real time' issue.
Change {'{getOrders()}'} to {'{getOrders(ORDERS_NEW())}'} and see if that improves things for you. If you want a watcher, you need a trigger. 😉
OK, looks like GE has messed around a bit with the functionality since I last reviewed it. I freed up some time and the following works.
You need TWO text components. The first loads the second.
Text Component #1 - Let's call it the 'loader' and it contains the code below:
{'{ADD_TEXT_COMP("Enterprise\Test", "Watcher Test") ""}'}
{FMT("New Orders:","B")}
{'{fnBuildNewOrders(ORDERS_NEW("delimited"))}'}
Text Component #2: Lets call it the 'library' and it contains the functions that the first text component references:
{fn fnBuildNewOrders(strList)
{
local retStr = ""
local strTemp = ""
local strBuf = ""
local i
strTemp = getfield(strList,"|","")
for i = 1, i <= size(strTemp), i = i + 1 do
strTemp[i] = getfield(strTemp[i],"^","")
strBuf = strTemp[i][1] + ", " + strTemp[i][3] + " on " + + strTemp[i][4] + HRET + " - Diagnosis: " + strTemp[i][6] + " (" + + strTemp[i][7] + ")" + HRET + " - Autho Provider: " + strTemp[i][21] + HRET + HRET
if retStr "" then
retStr = retStr + strBuf
else
retStr = strBuf
endif
endfor
return retStr
}
}
The output looks like this:
New Orders:
HDL, CPT-83718 on 05/11/2017
- Diagnosis: EDEMA (ICD-782.3)
- Autho Provider: Harry S. Winston, MD
Cholesterol, CPT-82465 on 05/11/2017
- Diagnosis: EDEMA (ICD-782.3)
- Autho Provider: Harry S. Winston, MD
Let me know if you have any questions.
Note in the function above, the website has stripped out the less than greater than in the line:
if retStr doesn't equal "" then
This works! It's really weird, though... The orders will display and will continue to display after the document is put on hold and reopened, but there is a that represents the function that calls the second text component that never goes away. If I delete it, the functionality ceases to work, because I've deleted the textual representation of the function!
I wonder if there is a way to hide text component text or functions... This is 99% of the way there, and that just might have to be good enough for our providers! Thanks for digging into this like you did. I really appreciate it.
Are you referring to the '<value>' statement in red? If yes, it must remain (it is the watcher placeholder). It will not be visible when on hold or after the chart is signed.
If you mean some of the code from the function is appearing in the note, be certain that you copied from here, pasted into Notepad, copied from Notepad, and pasted into the text component. This will help remove any hidden formatting codes. If that is clean and it still happens, you could try to terminate the function with twin double quotes after the 'return retStr'. Ie. return retStr ""
Yeah, I mean the red . We did notice that it doesn't show up in the note, so it won't be a problem. This is a pretty big win for us, so thank you for your help!
I'm now working on adding additional code to to separate out diagnoses and ICD10 codes, as many of our orders have more than one. I'm either going to add another for loop in there to list them side by side, or have them listed out vertically. If/when I get that working, I'll add the code here, just to keep a record for people in the future.