Read-Only and Mandatory workaround

xiaix
Tera Guru

Became victim of the famous Read-Only & Mandatory field problem.   But... I found a workaround (albeit a hack) and am curious if this is the best solution.   I'm worried about future compatibility with instance upgrades.

Here's the deal...

We have an HR form that has an "Employee ID" field, and a "Caller" (sys_user reference) field.   HR does not want to enter the name of the employee into the Caller field, but rather enter their Employee ID, upon which will auto-fill in the Caller field.

So, we needed the "Caller" field to be mandatory but read-only also.

The solution was to put a String field (not reference) on the form and make THAT read-only, not mandatory.   We then made the reference Caller field mandatory, and although we couldn't make it a read-only, we simply hid it via element.style.display = "none" in an onLoad client script.

The frustrating part was HR also wanted the "i" hover button to appear next to the Caller field so they could hover over it to get more Employee info.   Well that was a head-scratcher, so here's what we did.

Allow me to explain all steps:

First, the onChange client script that makes the User ID field auto fill in the hidden Caller field:

find_real_file.png

function onChange(control, oldValue, newValue, isLoading)

{

      if (isLoading)

              return;

      if (newValue == '')

      {

              g_form.setValue('u_caller', '');

              g_form.setValue('u_caller_display', '');

              return;

      }

      if (!g_form.getControl('u_caller'))

              return;

      var gr = new GlideRecord('sys_user');

      gr.addQuery('employee_number', g_form.getValue('u_userid'));

      gr.query();

      if (gr.next())

      {

              g_form.setValue('u_caller', gr.sys_id);

              g_form.setValue('u_caller_display', gr.name);

      }

      else

      {

              g_form.setValue('u_caller', '');

              g_form.setValue('u_caller_display', '');

              g_form.showErrorBox('u_userid', 'Invalid UserID');

      }    

}

Now, the onLoad client script that hides the reference Caller field, and copies the "i" info hover button up to the string Caller field and places it perfectly:

find_real_file.png

function onLoad()

{

      var outer = '';

      // First, capture the "i" reference icon code and stuff it into the "outer" variable

      var info = gel('view.u_human_resources.u_caller');

      if (info)

              outer = info.outerHTML;

      // Hide the real reference field that's mandatory, but not read-only

      var a = gel('element.u_human_resources.u_caller');

      if (a)

              a.style.display = "none";

     

      // Create the "i" hover button shell.   (it's just an <a> tag)

      var caller_info_hover_button = document.createElement('a');

      if (outer != '')

      {

              // Create an object of the String version of the Caller.

              // This should be a <div>, which contains other divs, the last one being the placeholder

              // for the "i" button icons to hover over.

              var u_caller_display_FIELD = gel('element.u_human_resources.u_caller_display');

             

              // Get the last <div> of the string Caller element

              var lastChild = u_caller_display_FIELD.lastElementChild;

             

              if (lastChild)

              {

                      // Append our "i" hover button shell we created above.

                      lastChild.appendChild(caller_info_hover_button);

                     

                      // Take all that copied info we did at the start and stuff it into this shell

                      caller_info_hover_button.outerHTML = outer;

              }

      }

}

End Result:

find_real_file.png

find_real_file.png

find_real_file.png

18 REPLIES 18

arnabwa
Giga Guru

Hi David,



I would not comment on the feasibility of this work around in the later releases because I'm relatively new as a developer but I must admit I'm impressed by the work around you have devised.


This is the only motive I'm adding my post here. Also this requirement has eaten up many snow developer's minds, hence this work around would turn out to be a blessing for them. Even I have been wondering about this hovering icon to be present beside a read-only non-reference field.



Thanks for being a part of the community.



Many Thanks,


Arnab


Thank you for the kind words.


My pleasure David.



Also I would like to have a watch on your code if you are going for a server side code for the same work around (as mentioned by Michel).


So please keep us posted.



Thanks.


rlatorre
Kilo Sage

If your HR department wants to select a user from a reference field using an attribute other than the display value you can setup the field to auto complete by additional fields using these attributes.



Dictionary attributes for auto-completion of reference fields



We use this on CIs to auto complete by name and serial number.



So, on the sys_user table collection, add attributes something link this:



ref_auto_completer=AJAXTableCompleter,ref_ac_columns=name;u_employee_id,ref_ac_columns_search=true,ref_ac_display_value=false