russ_sarbora
ServiceNow Employee
ServiceNow Employee

For the last several months I've been working on internal company projects. Almost all of our internal business applications are built on the ServiceNow platform, and I've been getting to develop some new ones as our company grows. While working on one, I encountered what I thought was a pretty simple problem, I needed to update some price fields on a form. But, it turns out, we didn't have a convenient way to do that out-of-the-box.

The problem is that a currency field consists of 3 different form elements. There is a hidden element that holds the "currency string" representation of the field. This looks something like "USD;100.00", and then there are 2 visible elements that show the components of that representation ("100", and "$") to the user and allow them to modify it. Changing a currency field via script means you have to change all three of these fields. That's unpleasant if you have to change 1 or 2 fields, but I had 12 currency values that all needed updating at the same time (its a finance app) and there was no way I was writing 36 lines of repetitive code when I could avoid it. So I decided to add a setCurrencyField() method. its fairly simple, just setting all three fields for us in one shot:


function setCurrencyField(fldName, currency, amount) {
g_form.setValue(fldName+'.display', amount);
g_form.setValue(fldName+'.currency', currency);
g_form.setValue(fldName, currency+';'+amount);
}


Personally, I feel like this is really something that should be a part of the g_form object, so I decided to add it there. To do that, we need to add it the GlideForm.prototype, and then voila, all of our g_form instances will have that method. A slight refactoring to the above will do the trick:

GlideForm.prototype.setCurrencyField = function(fldName, currency, amount) {
this.setValue(fldName+'.display', amount);
this.setValue(fldName+'.currency', currency);
this.setValue(fldName, currency+';'+amount);
}

The real question is where to put that script? Since all of this needs to happen on the client side, we can use either a Client Script or a UI Script to do it. It needs to run globally, so that it works for any form in the system. When I hear client-side and global I think UI Script. So I added a global UI Script called GlideFormExtension and added the new function in there. The result, from any form I can set currency values through script:


g_form.setCurrencyField('netPrice', '$', '100.00');

Note: There is a small issue in this implementation. If the dictionary entry on your currency field is marked "read-only" the script will not correctly update the form display (but if you make it read-only via a UI policy or client script it will work). The problem is that the read-only version of the field doesn't use the same 3-headed form element model. It shouldn't be difficult to make our setCurrencyField work with the read-only version, I just haven't had a need for it so far.

9 Comments