logo

NJP

How To Implement GlideAjax with 1 LOC [Part 5 - Auto Populating Fields]

Import · Oct 14, 2020 · article

I've been using my own SmartAjax scripts on almost every implementation I work on, as it saves so much time and makes retrieving server-side data so simple. I'm always trying to think of ways to improve my existing code, so I decided to refine SmartAjax even further.

The Common Use Case

The most common form of GlideAjax code usually goes something like this:

  • For a particular record that is referenced on my form
  • When that field changes value
  • Get some fields from that record
  • Populate my form based on that record

I still found myself re-writing the same code in my callback function, which would usually go something like this:

var caller = s_ajax.getReference('caller_id',callback,['location','department']);

function callback(caller) {

    if (caller.hasOwnProperty('department')) {
        g_form.setValue('my_department_field', caller.department, caller.getDisplayValue('department'));
    } else {
        // If user has no department, clear value
        g_form.clearValue('my_department_field');
    }

    if (caller.hasOwnProperty('location')) {
        g_form.setValue('my_location_field', caller.location, caller.getDisplayValue('location'));
    } else {
        // If user has no department, clear value
        g_form.clearValue('my_location_field');
    }

}

I wanted to codify this pattern while keeping to 1 LOC, so I created the Class SmartAjaxFieldMapper.

SmartAjaxFieldMapper

The syntax is as follows:

new SmartAjaxFieldMapper('caller_id')
    .addFieldMapping('my_department_field','department')
    .addFieldMapping('my_location_field','location')
    .getReference();

The API will then automatically populate the fields based on reference values.

SmartAjaxFieldMapper is just a deceivingly simple wrapper around s_ajax that simplifies the callback.

It has the following class variables

var referenceField;
var fieldMappings = {};
var fieldsToGet = [];

addFieldMapping() functions return this, allowing you to stack mappings:

  addFieldMapping: function(fieldName, refField) {
    if (g_form.getElement(fieldName)) {
        fieldMappings[fieldName] = refField;
        fieldsToGet.push(refField); // Used for s_ajax
    } else {
        log(fieldName + ' is an invalid field name and will not be mapped');
    }
    return this;
},

getReference() function just uses a premade callback function that codifies the common use case pattern:

function mapFields(response) {

    for (var fieldName in fieldMappings) {
        var refField = fieldMappings[fieldName];

        if (response.hasOwnProperty(refField)) {
            g_form.setValue(fieldName, response[refField], response.getDisplayValue(refField));
        } else {
            g_form.clearValue(fieldName);
        }

    }

}

You can even pass is your own callback function if you would rather do something more complex:

var complexFunction = function(caller) {
   alert(caller.getDisplayValue('department'));
}

new SmartAjaxFieldMapper('caller_id')
    .addFieldMapping('my_department_field','department')
    .addFieldMapping('my_location_field','location')
    .getReference(complexFunction);

Another example with the console:

var helloWorld = function(caller_id) {
    alert(caller_id.email);
}

new SmartAjaxFieldMapper('caller_id')
.flashFieldsOnChange()
.addFieldMapping('short_description','user_name')
.addFieldMapping('location','location')
.addFieldMapping('invalid_field_name','locations')
.addField('email')
.getReference(helloWorld);

image

image

This new API is available via the existing SmartAjax Share App.

It can also be used in Service Portal, just like SmartAjax

new SmartAjaxFieldMapper('refvar',g_form)
    .addFieldMapping('var1','department')
    .addFieldMapping('var2','location')
    .getReference();

If you liked this blog, please check out and bookmark some of my others here image

View original source

https://www.servicenow.com/community/developer-blog/how-to-implement-glideajax-with-1-loc-part-5-auto-populating/ba-p/2280716