Member Avatar for diafol

Hi All. I have been struggling with a form wizard all day. I'm using jquery stepy (form wizard) along with validation plugin.

To cut a long story short, my first step is to get MySQL connection from form controls details. On submit ('next' button) a check is made on an empty hidden control ('hid').

rules: {
	hid: {
	required: function(){
	       return checkDBData();
        },
messages: {
	hid:
		{required: 'SQL not available'},
...(etc)...

So, if the function checkDBData passes, false should be returned, so that the form can progress to the next step. If the connection details fail, true is returned so that an error msg is posted.

Here's the checkDBData function:

function checkDBData(){
	var host = $('#mysql_host').val();
	var username = $('#username').val();
	var password = $('#password').val();
	var dbname = $('#dbname').val();
	
	$.post(	"install/sqlcheck.php", 
		   	{"host": host,"username": username, "password": password, "dbname": dbname},
		   	function(msg){
				
				if(msg.required == false){																												
			 		return false;
				}else{
					return true;
				}
			},
			"json"
	);
	
}

the return values don't find their way back to the rules. However, if I hard code false and true to the function...

function checkDBData(){
	var host = $('#mysql_host').val();
	var username = $('#username').val();
	var password = $('#password').val();
	var dbname = $('#dbname').val();
	
	$.post(	"install/sqlcheck.php", 
		   	{"host": host,"username": username, "password": password, "dbname": dbname},
		   	function(msg){
				
				if(msg.required == false){																												
			 		return false;
				}else{
					return true;
				}
			},
			"json"
	);
     return false; //or return true for testing purposes	
}

This works.

I assume it's due to the asynchronous nature of the ajax call. Any ideas?

Recommended Answers

All 2 Replies

Hi Ardav,

Yes you're spot on, asychronous structure of jquery.post() makes nonsense of returning a value from the anon (success) fn.

There's a couple of approaches:
1. You can write the rules... code (and whatever uses rules) inside the anon fn, like this:

function checkDBData() {//You may well need to pass in data/objects as required by the rules... code.
	var host = $('#mysql_host').val();
	var username = $('#username').val();
	var password = $('#password').val();
	var dbname = $('#dbname').val();
	$.post("install/sqlcheck.php",
		{"host": host,"username": username, "password": password, "dbname": dbname},
		function(msg) {
			... preamble ...
			rules: {
				hid: {
				required: msg.required,
			messages: {
				hid:
					{required: 'SQL not available'},
			...(etc)...		},
		"json"
	);
}

2. A neater approach is to pass a callback function to checkDBData.

function checkDBData(callbackFn) {
	var host = $('#mysql_host').val();
	var username = $('#username').val();
	var password = $('#password').val();
	var dbname = $('#dbname').val();
	$.post("install/sqlcheck.php",
		{"host": host,"username": username, "password": password, "dbname": dbname},
		function(msg) {
			callbackFn(msg);//must pass msg as it's not otherwise available to the callback code.
		},
		"json"
	);
}

Then call checkDBData (from the same scope as your current rules...) as follows:

checkDBData(function(msg){
	... preamble ...
	rules: {
		hid: {
		required: msg.required,
	messages: {
		hid:
			{required: 'SQL not available'},
	...(etc)... }
});

Approach 2 has the advantage that the rules... code is defined in an inner function within the same scope as you currently have it. It will therefore have access to any variables/objects within (or available to) that same scope. Hence no need to pass further values to checkDBData.

Either of these should be reasonably straightforward but things would be trickier if you needed to go server-side more than once during the validation. In that case, you could :

  • somehow accumulate the responses in some outer object and act when all responses have been returned (potentially messy)
  • aggregate all server-side aspects into a single php script and obtain a composite response (much simpler as you're already using JSON, though it may go against existing server-side strategy).

Airshow

commented: This shows me how much I have to learn about JS! +8
Member Avatar for diafol

Ahhh. A weight has been lifted...

Method two looks really neat. I'll give it a go.

I'm ashamed to say I went will a 'async = false' method on the jQuery.ajax and ditched the json for responseText. It all went horribly wrong! It worked, but I couldn't help thinking that it was a total fudge.

I won't be doing more than one round trip, so method two should be fine. Thanks again - once again.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.