While loop query + iteration

David Post
Kilo Expert

I'm putting together a script include to look up user IDs as part of new user creation. I want to look up records on the sys_user table for matches on the user_name attribute equal to the default format.

That's not a problem:

	validateEmail: function() {
		var firstname = this.getParameter("sysparam_firstname");
		var lastname = this.getParameter("sysparam_lastname");
		var username = firstname+'.'+lastname; //nice little string here
		var validate = new GlideRecord('sys_user');
		validate.addQuery('user_name', username);
		validate.query();

Note: domain is being used for another part

Where I get into trouble is when there's a match - which will happen. It's at this point I [think that I] need to do a while loop, but i'm unsure of what context the query is returning. I believe it is returning a record, but it might be Boolean. Either way, I need to set up a while loop that:

  1. runs until a record is NOT found, but also
  2. iterates through my naming convention until the condition is met
		while (validate.next()) {
			var suffix = 1;
			var username = user_name+'.'+suffix;
			var validate = new GlideRecord('sys_user');
			validate.addQuery('user_name', username);
			validate.query();
			suffix++;
		}

think this adds '.1' to the end of the user name (john.smith.1), and iterates onwards (john.smith.2) until it fails to find a match, at which point the  'username' variable will have been set to the value that isn't matched against the sys_user table.

Then we return the username variable as a string (added the '') at the end, forcing a string format.

		return username+'';

If all that works, we're going to parse the returned data and fill out the field on the catalog item:

function validateEmail(response) {
		var username = response.responseXML.documentElement.getAttribute("username");
		g_form.setValue('username', username);
	}

...and use that data to set the email address as well.

	g_form.getValue(company); //the value of the variable is actually the domain info
	g_form.setValue('email_address', username+'@'+company);
	g_form.setReadOnly(username);
	g_form.setReadOnly(email_address);

 

Lacking a team, I need a code review. Tell me where I'm crazy!

Client script:

function onChange(control, oldValue, newValue, isLoading) {
   if (isLoading || newValue == '') {
      return;
   }
	
	g_form.addInfoMessage("Identifying available username and email.");
	
	var first = g_form.getValue(first_name);
	var last = g_form.getValue(last_name);
	
	var ga = new GlideAjax('newUserUtils');
	ga.addParam('sysparam_name','validateEmail');
	ga.addParam('sysparam_firstname', first);
	ga.addParam('sysparam_lastname', last);
	ga.getXML(newUserUtils);
	
	function validateEmail(response) {
		var username = response.responseXML.documentElement.getAttribute("username");
		g_form.setValue('username', username);
	}
	g_form.getValue(company); //the value of the variable is actually the domain info
	g_form.setValue('email_address', username+'@'+company);
	g_form.setReadOnly(username);
	g_form.setReadOnly(email_address);
   
}

Script include: 

var newUserUtils = Class.create();
newUserUtils.prototype = {
    initialize: function() {
    },
	
	//Identify the most desireable email address available for the new user
	validateEmail: function() {
		var firstname = this.getParameter("sysparam_firstname");
		var lastname = this.getParameter("sysparam_lastname");
		var username = firstname+'.'+lastname; //nice little string here
		var validate = new GlideRecord('sys_user');
		validate.addQuery('user_name', username);
		validate.query();
		//try (email.next()) 
		while (validate.next()) {
			var suffix = 1;
			var username = user_name+'.'+suffix;
			var validate = new GlideRecord('sys_user');
			validate.addQuery('user_name', username);
			validate.query();
			suffix++;
		}
		
		return username+'';
		
	}
	
    type: 'newUserUtils'
};

 

THANK YOU all for checking this out!

1 ACCEPTED SOLUTION

Remember to correct 

		if (COUNT > 0) {

to 

		if (userCount > 0) {

And I can spot that your Script include is not "Client callable". The first part should look something similar to this: 

var newUserUtils = Class.create();
newUserUtils .prototype = Object.extendsObject(AbstractAjaxProcessor, {

 

It is achieved by making "client callable" to true on the script include! It needs this to work with GlideAjax 🙂  

That is the first step, else it can't be called from the client side! 🙂

 

I would also move all your g_form action just after 

		g_form.setValue('username', answer);

 

So you make sure that everything runs the same time, and after getting the answer from the server!


Best regards,
Sebastian Laursen

View solution in original post

7 REPLIES 7

No problem! I edited the code above, saw I had written count instead of userCount in the if!


Best regards,
Sebastian Laursen

Hmmm. Client script (final):

function onChange(control, oldValue, newValue, isLoading) {
   if (isLoading || newValue == '') {
      return;
   }

	g_form.addInfoMessage("Identifying available username and email.");
	
	var first = g_form.getValue(first_name);
	var last = g_form.getValue(last_name);
	
	var ga = new GlideAjax('newUserUtils');
	ga.addParam('sysparam_name','validateUsername');
	ga.addParam('sysparam_firstname', first);
	ga.addParam('sysparam_lastname', last);
	ga.getXML(newUserUtils);
	
	function validateUsername(response) {
		var answer = response.responseXML.documentElement.getAttribute("newUsername");
		g_form.setValue('username', answer);
	}
	
	g_form.getValue(email_domain); 
	g_form.setValue('email_address', answer+'@'+email_domain);
	g_form.setReadOnly(username);
	g_form.setReadOnly(email_address);
    g_form.clearMessages();
	g_form.addInfoMessage("Username and email address identified."); 
	
}

 

Script include (final):

var newUserUtils = Class.create();
newUserUtils.prototype = {
    initialize: function() {
    },
	
	//Identify the most desireable email address available for the new user
	validateUsername: function() {
		var firstname = this.getParameter("sysparam_firstname");
		var lastname = this.getParameter("sysparam_lastname");
		var newUsername = firstname+'.'+lastname; //nice little string here
		
		var userCheck = new GlideAggregate('sys_user');
		userCheck.addQuery('user_name', 'STARTSWITH', newUsername);
		userCheck.addAggregate('COUNT');
		userCheck.query();
		userCheck.next();
		var userCount = userCheck.getAggregate('COUNT');
		
		if (COUNT > 0) {
			newUsername = newUsername+'.'+userCount;
		}
		
		return newUsername+'';
		
	}

   //type: 'newUserUtils'
};

 

The catalog item doesn't seem to do anything after sending the addInfoMessage on line 6 of the client script. You'll see i commented out the 2nd to last line of the script include because it won't compile (JavaScript parse error at line (27) column (8) problem = missing } after property list (<refname>; line 27)).

 

It seems I've missed something core about the whole client script > script include process.

Remember to correct 

		if (COUNT > 0) {

to 

		if (userCount > 0) {

And I can spot that your Script include is not "Client callable". The first part should look something similar to this: 

var newUserUtils = Class.create();
newUserUtils .prototype = Object.extendsObject(AbstractAjaxProcessor, {

 

It is achieved by making "client callable" to true on the script include! It needs this to work with GlideAjax 🙂  

That is the first step, else it can't be called from the client side! 🙂

 

I would also move all your g_form action just after 

		g_form.setValue('username', answer);

 

So you make sure that everything runs the same time, and after getting the answer from the server!


Best regards,
Sebastian Laursen