Credit for figuring these out/discovering them goes to Perry. I find myself referring to them in a training binder I got from last year’s NY Training Summit and figured it would be easier to just get them up on the web so I don’t have to go hunting for that binder every time. The following code works for Classic.
Subform Considerations
Subforms have to be handled differently than forms when it comes to JavaScript because while in the form designer, the two things look identical, the way that myEvolv renders a subform in the browser is very different from how it renders a form. But it isn’t radically different and the main changes account for the fact that a subform can have one or more rows and so you need to be more specific about which field you are trying to manipulate so that you don’t change every line simultaneously.
Scenario 1: Get the Value of a Subform Field
This code is for use within the subform, e.g. if you want to default the value of one field based on the value of another on the same subform.
self.getElementFromXML(currentRowXML, 'column_name');
Note the self
object is being used here. This is the subform object as distinguished from the parent form object. The parameter currentRowXML
then further narrows it down to the current record/row on the subform that you are concerned with.
Scenario 2: Set the Value of a Subform Field
Again, for use within a subform, this code can be used to set the value of a field in the same subform, e.g. when you want the On Change event to auto-populate a field.
this.form.'column_name'.value;
If you are checking a checkbox, use this code:
this.form.'column_name'.checked = true;
Note that in this code, you do keep the single quotes in the code for it to work properly. All you change is the column_name
Scenario 3: Get the Value of a Parent Form Field
With this code, you can get the value of a field in the parent form based on an action in the subform.
window.parent.getFormElement('column_name');
Note the window.parent
is the only difference from the code you would use on the parent form. This is what allows your code to ‘jump up out of the subform’.
Scenario 4: Set the Value of a Parent Form Field
Maybe you figured it out by now but you can use the same small change to set values on the parent form from the subform.
window.parent.setFormElement('column_name', value);
Scenario 5: Trigger an Alert from the Subform
Alerts are useful in guiding user activity and you can trigger them from subforms. Similar to the last two, the trick is moving back up the DOM to the parent form to trigger it.
window.parent.window.alert('Alert Message');
Other Possibilities
It is possible to go the other way and get and set values on subform records from the parent form, however, it becomes a much more complex problem that requires very specific solutions for very specific challenges. That is because of the One-to-Many relationship that the subforms have with the parent form. For these types of situations, you will probably be targeting the subform itself and then looping through each record to get or set values.
I did find another Netsmart function in the …classic/scripts/inbrowseFunctions.js called setSubFormElement that is similar to SetFormElement, but takes an extra first parameter that specifies the subform. In addition to assigning the value it does (among other things) refresh the displayed value for lookup fields.
It seems to work well most of the time, but fails to refresh the displayed value of the lookup field if the Display Type of the field is not FK. I learned this in applying the function to the personal address City field for which the value stored and displayed is the city name (not an ID) and the Display Type is S. Reviewing the code for this function, however, allowed me to include my own script in the form designer that would refresh the display value in this particular case instead of calling setSubFormElement.
It also seems that if you’re self-hosted and so inclined, one could add GetFormElement and SetFormElement functions to the the inbrowseFunctions.js file to enable support for these functions in the Classic application for subforms. I think including this functionality is something Netsmart should do and could do without much difficulty in order to simply the transition from Classic to NX for users.
Hi Michael,
Nice find. Thanks for sharing it. I am going to have to mess around with that one when I get a chance.
Pardon the second post. Using the “this” object construction of the subform get/set works in Evolv Classic but not NX. Using the setSubFormElement construction works in NX but not in Classic. Just to clarify.
Hello Dean,
I am trying to add up the values within a subform column. Do you know how to get the column value for all rows within a subform? Is there an alternative to the currentRowXML parameter within self.getElementFromXML(currentRowXML, ‘column_name’); that would return all rows? What data type is currentRowXML?
currentRowXML
is a JavaScript variable that contains the XML object for that specific row of the subform. What you are trying to do is possible to do, but I have not attempted it yet myself to be able to provide you with rock solid example code, unfortunately.formXML
is a JavaScript variable that myEvolv initializes when you open a form and it is an XML object for the entire form, parent elements, subforms, subreports and all. When values are updated on the form, they are also updated in the formXML Document Object Model so that they mirror one another. Similarly, when a new row is added to a subform, a new node of the XML DOM that describes that row is created and contains subnodes for each column and the attributes and value that they hold. You can think ofcurrentRowXML
as being a node within this largerformXML
object.It sounds like what you would probably do is use some Before Save code to go through the subform nodes and get and sum the values for the same one column in all rows and then updating a parent form value so that it is contains the sum value before the save function executes. You should be able to accomplish it if you know how to do (or learn how to do) what is called “traversing the node tree”. Here is a link to the W3 Schools page on the topic. https://www.w3schools.com/xml/dom_nodes_traverse.asp
This is sort of the pattern you might follow, again not tested or verified in any way:
var sumAmount = 0;
var subFormRowValues = formXML.documentElement.selectNodes(\'\'form_group/form_item/form_object[@formCode='MY_SUBFORM_CODE']/form_group/form_item[@column_name='my_udf_subform_column']\'\')
for (var i = 0; i < subFormRowValues.length; i++){{
sumAmount += subFormRowValues[i].text;
}}
setElementFromXML(formXML, 'my_sum_element', sumAmount);
To start, swap out the form code for the subform you are using, the column that your values to be summed are in and then parent form element you will be saving the sum in.
You may need to change the path in the second line to properly traverse the nodes. I just took this from some code I found in formfunctions.js that looked close to what you seem to be trying to do.
Good luck and let me know if you get it going.
-Dean
Dean,
Thank you for the reply. I am still trying to figure out the correct path to use in the second line, but I think you pointed me in the right direction. I appreciate your help and will let you know if I end up getting it to work.
I’m new to my Evolve and am responsible for custom building my agency’s forms. I have some conceptual ideas about what I’m trying to accomplish, but am still trying to wrap my head around the capabilities of subform / subreports then apply to my organization’s workflows. All that was described above looks genius, but can anyone point me to a post that would describe practical applications for these manipulations?
Our agency is willing to pay for a consultant who could work collaboratively with me to custom design our form buildout and train me to manage moving forward. We belive in the capability of MyEvolve, but our implementation team has been very unhelpful and limited thusfar in training us how to build custom forms. We received a two day training teaching us how to build basic assessments like GAD-7 before we were even proficient w/how to add clients or the basic functionality of MyEvovle, which went way over our heads at the time.