WordPress.org

Ready to get started?Download WordPress

Forums

[resolved] Nested Select Menu (22 posts)

  1. A31
    Member
    Posted 8 months ago #

    Hi,
    I am really struggling to get a second dropdown / select box to be automatically populated and I hope someone here can help me find my mistake.

    Before moving to WordPress, I have been using the example by W3Schools but now in wordpress, I can't seem to get it working.

    My Code is as follows:

    <script type="text/javascript">
    function showUser(str)
    {
    if (str=="")
      {
      document.getElementById("txtHint").innerHTML="";
      return;
      }
    if (window.XMLHttpRequest)
      {// code for IE7+, Firefox, Chrome, Opera, Safari
      xmlhttp=new XMLHttpRequest();
      }
    else
      {// code for IE6, IE5
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
    xmlhttp.onreadystatechange=function()
      {
      if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {
        document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
        }
      }
    xmlhttp.open("GET","Fin_GetAllocation.php?q="+str,true);
    xmlhttp.send();
    }
    </script>
    <form>
    	<select name="sel_CostCentre" id="sel_CostCentre" onchange="showUser(this.value)">
    		<option value=0>Please Select Cost Centre: <?php echo $CostCentreDescriptionOptions; ?>
    	</select>
        <select name="Sel" id="txtHint"></select>
    </form>

    then the code in the file "Fin_GetAllocation.php" is as follows:

    <?php
    	global $wpdb;
    
    	$q=$_GET["q"];
    
    	$SQL_Query01 = ("SELECT * FROM wp_allocations_tbl WHERE CostCentreDescription = '$q'");
    	$SQL_Results01 = $wpdb->get_results($SQL_Query01);
    
    	foreach($SQL_Results01 as $myResult01)
    		{
    			$AccountDescription = $myResult01->AccountDescription; //Field in DB
    			$AccountDescriptionOptions.="<option value='$AccountDescription'>" . $AccountDescription . "</option>";
    		}

    So my first dropdown / select box works perfectly, but I can't seem to get the second box to populate.

    Can you please help?

  2. bcworkz
    Member
    Posted 8 months ago #

    AJAX in WordPress is handled differently than as is done with other webpages. See AJAX_in_Plugins. Another reference still being developed is http://make.wordpress.org/docs/plugin-developer-handbook/plugin-components/improve-ux-with-ajax/.

    If you can suggest any way to improve the second document, or if certain parts do not make sense to you, your feedback is appreciated. You can leave comments on the page once you register for "Make". Besides this forum, I'm involved with the Developer Handbooks effort.

  3. A31
    Member
    Posted 8 months ago #

    Thank you very much!

    I think your new documentation is clear and well written, and I already picked up on some of the mistakes I've made. However, this is my first attempt to really using Ajax (the above code I understood as Javascript), and well... I don't really understand how to implement this to a nested / multi-leveled dropdown list box.

    Is there perhaps any possibility that you could teach me how to do that or maybe even include such an example in your documentation?

    Thank you very much for your help so far!

  4. A31
    Member
    Posted 8 months ago #

    Ok I have tried a number of different methods and I am now so confused... most of these methods are so much more code than my origional code as well...

    So I tried to simplify as much as i could and went back to what I knew worked. I tested it outside of WordPress and it works 100%, inside WordPress... not at all.

    I understand that WP manages all these things differently, can you please teach me how to put this simplified code of mine into a working WordPress format?

    Form.php

    <?php
    	global $wpdb;
    ?>
    <form>
    	<select name="sel_CostCentre" id="sel_CostCentre" onchange="showUser(this.value)">
    		<option selected="selected">Please Select...</option>
    	    <option value="Expense">Expense</option>
    	    <option value="Income">Income</option>
    	</select>
        <select name="Sel" id="txtHint"></select>
    </form>
    
    <script type="text/javascript">
    function showUser(str)
    {
    if (str=="")
      {
      document.getElementById("txtHint").innerHTML="";
      return;
      }
    if (window.XMLHttpRequest)
      {// code for IE7+, Firefox, Chrome, Opera, Safari
      xmlhttp=new XMLHttpRequest();
      }
    else
      {// code for IE6, IE5
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
    xmlhttp.onreadystatechange=function()
      {
      if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {
        document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
        }
      }
    xmlhttp.open("GET","GetData.php?q="+str,true);
    xmlhttp.send();
    }
    </script>

    GetData.php

    <?php
    
    $q=$_GET["q"];
    
    $i = 0;
    while ($i < 5)
    {
    	return "<option value='$i'>$q $i</option>";
    	$i++;
    }

    If i can just get this simple code to return the value through wordpress, it will surely help me to resolve this problem.

    Can you please show me how to convert this code into WordPress Format?

    Thank you again for all your help!!!

  5. bcworkz
    Member
    Posted 8 months ago #

    The main reason conventional AJAX does not work with WP is all requests MUST be channeled through wp-admin/admin-ajax.php. All other sites of course do not have such a page. Also, all requests MUST have an 'action' parameter passed because it is used in part to form the action tag your PHP code must hook into.

    I'm not entirely sure how to pass an 'action' in your pure javascript code, I always use jQuery because it is part of the WP installation and it is much easier. You could probably append it to the URL admin-ajax.php?action=my-ajax-request, or learn to use jQuery :)

    The final WP thing you need to do is execute your PHP code by hooking into the appropriate action. Both the references show you how to do that, it is not optional. Also, for data to be sent to the browser as a response to a request, it must be echoed, not returned. Rather than getting your code to work with WP, I would suggest you implement one of the examples in the references and see that it works in your installation.

    Once that works, then alter it to work with a single value of your code. Once you get a single value communicated, work on a single nested value. After that it should be a matter of just adding data in loops.

    If you can get a basic communication established, incrementally making changes to working code is much more reliable than coding everything then ironing out bugs one by one.

    I can't (OK, won't ;) ) write a custom tutorial for you. You are going have to do your own work in large part. I will try to keep you from going too far astray though. As I suggested, first get one of the examples working, that can be more challenging than it seems. Then start altering the example to meet your needs, a little at a time, constantly testing all is as expected after each small change.

    Check back in here when you get stuck and we'll see what we can do to get you back on track. Good luck!

  6. A31
    Member
    Posted 8 months ago #

    Hi there,

    Thank you very much for your help so far, I fully understand that you wish me to figure this out on my own. I am however very confused :-(
    I do not know which part of code goes where and how that applies to the front-end because from what I understand from the many many articles is that it differs.

    Also I am a bit unsure, do I have to put it in a separate .js file?

    I am sorry that I am so clueless, but am trying to learn.

    What I have done is taken the most basic AJAX jQuery example i could find that is in the general direction of what I am looking for and tested it without WP. All it does is it posts info from a form to a seperate data file and gives an alert box with the data.

    the php file:

    <?php
    	global $wpdb;
    
    	// Get Page Links
    	$MyData_PageTitle = 'MyData';
    	$MyData_page = get_page_by_title($MyData_PageTitle);
    	$MyData_myID = $MyData_page->ID;
    	$MyData_Link = get_page_link($MyData_myID);	
    
    	echo $MyData_Link;
    ?>
    	<script type="text/javascript">
    		$(function(){
    			$('#ff').form({
    				success:function(data){
    					$.messager.alert('Info', data, 'info');
    					//$.document.write('Info', data, 'info');
    				}
    			});
    		});
    	</script>
    		<form id="ff" action="<?php echo $MyData_Link; ?>" method="post">
    			<table>
    				<tr>
    					<td>Name:</td>
    					<td><input name="name" type="text"></input></td>
    				</tr>
    				<tr>
    					<td>Email:</td>
    					<td><input name="email" type="text"></input></td>
    				</tr>
    				<tr>
    					<td>Phone:</td>
    					<td><input name="phone" type="text"></input></td>
    				</tr>
    				<tr>
    					<td></td>
    					<td><input type="submit" value="Submit"></input></td>
    				</tr>
    			</table>
    		</form>

    then the MyData.php file:

    <?php
    
    $name = $_POST['name'];
    $email = $_POST['email'];
    $phone = $_POST['phone'];
    
    echo "Your Name: $name <br/> Your Email: $email <br/> Your Phone: $phone";
    
    ?>

    but Alas, it is not working :-( I am terribly confused.

    Can you please help?

  7. bcworkz
    Member
    Posted 7 months ago #

    Don't get too distressed because something doesn't work, it happens to the best of us. It's often just a silly mistake. Of course when you don't yet understand what's going on, finding that silly mistake can be overwhelming. Don't stress, we'll get it worked out eventually. Learning to debug is an essential skill. What better way to learn than make mistakes?

    The problem here is you've introduced yet another element you've yet to adequately learn... jQuery. I applaud the effort, it will pay off eventually. What your simple example's source had apparently omitted to inform you, assuming everyone using jQuery would know this, is you need to reference the jQuery library in the page's head section. Without that, it will fail no matter what. I'm not going to get into how to do this in your trial script because once again, how it is done in WP is different.

    You really need to start with a simple WordPress AJAX example. Even though such examples appear more complicated, you're adding needless confusion by learning one way and then needing to relearn the WP way.

    As I believe you realized, whether to use an external js file or inline script is a fundamental decision one must make. Either way works, inline makes more sense for simple, short scripts, the external file makes more sense for larger scripts or projects where separation of various components is organizationally cleaner.

    I personally use external js files for even basic scripts because it works for any project of any size. I have a single setup I use, it works for everything of any size. I'm less confused by doing things the same way every time.

    I'm sure others will argue that it's stupid to generate another file request for a dozen lines of code, inline script is more efficient. They're right. But I don't care, my clients have low volume sites, it's not a big deal, and it keeps me organized. I'm set if their script needs grow.

    The other thing to decide is where to put this stuff. Your choices are child theme or plugin. For customizations to your own site, I would suggest a child theme makes the most sense. You might eventually find some admin thing you need to customize requires a plugin, but virtually anything can be done from a child theme. Child themes make it easy to utilize the best way to introduce custom code pages into WP, the custom page template.

    The page template contains the front end form. If your form is for the admin area, then perhaps a plugin makes more sense. Then your form is introduced using the Settings API and maybe the Administration Menus API. Let's keep things simpler and focus on a front end page template. Any PHP page can be made into a template by adding the following comment as the very first thing on a page:

    <?php
    /*
    Template Name: My AJAX Form
    */

    Place the file in your child theme folder, name it anything meaningful with a .php extension. Add a new page to WP using the Add New Page admin screen, assigning a title and basing it on your custom template. This gives you a permalink with which to access the page. Unless you build in a provision to do something with content, there is no reason to add content when creating a page based on your custom template.

    Submitting an entire form via AJAX is not illustrating its best use. Let's do a check on the email to confirm it's a valid format as soon as the user enters it (on the "change" event). You could do this with javascript alone, but let's let the server do it. Add an ID attribute to the email field: id="ffemail" to make it simple to reference the email field. jQuery has a rich set of selectors (its best feature IMO) where such IDs are not required, but an ID simplifies things.

    Here is minimal jQuery to submit the email via AJAX and display the result in an alert box. Take some time to ensure you understand every line. Place it in a file called myscript.js and place it in your child theme folder.

    jQuery(document).ready(function($) { //no conflict wrapper
       $("#ffemail").change(function() {
          var email = $(this).val();  //'this' is out of scope in .post() data array
          $.post("http://example.com/wp-admin/admin-ajax.php",
          { action: "myajax",   // define data array
    	addr:    email
            /* add localized nonce later */
          },
          function(data) {  // handle server response
             alert(data);
          });
       });
    });

    Edit the .post() URL to be your actual URL for your site. This should normally be a localized value, but we will skip that part for now. A nonce is another localized value we will skip over, though it is an important security measure.

    The PHP to reference or "enqueue" your script and to actually handle the AJAX request can go on your child theme's functions.php:

    add_action('wp_enqueue_scripts', 'my_queue');
    function my_queue() {
       //we eventually will only enqueue for the one page
       wp_enqueue_script( 'my-script',
          get_stylesheet_directory_uri().'/myscript.js',
          array('jquery')  // causes the jQuery library to be loaded
       );
       //add localize script stuff here later
    }
    
    add_action('wp_ajax_myajax', 'ck_emailfake');
    add_action('wp_ajax_nopriv_myajax', 'ck_emailfake');
    function ck_emailfake() {
       //add nonce and capability checks later
       echo $_POST['addr'].' email not checked!';
       die;   //all AJAX handlers must die!
    }

    This code should work for you unchanged except for your site URL. I did test it. But don't be surprised if it doesn't work at first. It's just the nature of coding that something will go wrong. I've added a few hints as comments and noted where important stuff should be added later. Again, take the time to understand every line. This knowledge is essential for being able to track down bugs and find mistakes.

    Note that we are not really checking the email format, we are just passing the entered value back and forth to demonstrate round trip data communication.

    I'll give you one more thing because it's a little obscure. The reason the AJAX handler is added to two different actions is the page could be accessed by someone logged in or not. Each state requires a different action hook. You're on your own to learn the rest :)

    Once you've figured out this basic code, building on that to reach your original goal of nested dropdown forms is closer than you think. Good luck, and try to have fun.

  8. A31
    Member
    Posted 7 months ago #

    Hi there bcworkz,

    Hope you have a wonderful 2014!

    Thank you very much for your help and your advice above, in some way pointed me into the right direction. Although I did not make use of the child-theme setup, I applied some of this information to a custom plugin.

    What I have managed to accomplish is the following:

    I can now run jquery from a wordpress plugin, which was one of the biggest goals !! :-) yay!

    One example would be:

    in my form.php file:
    at the top i have:
    `
    <div id="responsecontainer"></div>
    `
    then in the form section i have:
    `
    <input name="ItemCost" id="ItemCost" type="text"/>
    `
    then in my ajax.js file:

    jQuery(document).ready(function () {
    $("#ItemCost").change(function()
    	{
                $("#responsecontainer").html($("#ItemCost").val());
    	});
    });

    the moment my ItemCost value changes, it works beautifully, and returns the value to the response div.

    All is not solved yet though :-(
    This is what I ultimately want to achieve...

    What I have currently in my form is a select box:

    <select name="MySel" id="MySel">
    <option value="">Please Select... </option>
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    </select>

    my jquery in my ajax.js file looks like:

    jQuery(document).ready(function () {
    $("#MySel").change(function() {
    
    	$.ajax({
            type:"POST",
            url: "GetData.php",
            datatype: "json",
            success: function(data, textStatus, xhr) {
            data = JSON.parse(xhr.responseText);
    
            $("#responsecontainer").html(data);
         }
    
         });
    });
    });

    my GetData.php file contains the following:

    $ReturnedValue = "Returned Data";
    
    echo json_encode($ReturnedValue);

    very simple I realise, but only to test.
    So really at this stage it does not matter what the user chooses in the select box, I just want to return the data from the GetData.php file to the response <div>.

    Up to now however, I can't seem to get the data back from the GetData.php file, can you please help me in returning the data to the form?

    You really do help me!
    Thank you so much for all your help!!

  9. bcworkz
    Member
    Posted 7 months ago #

    Hello, a great new year for you too!

    It's really cool once you get something working, isn't it? :)

    AFAICT, the only issue with your jQuery code is you forgot to pass the '$' shortcut character in your wrapper function.
    jQuery(document).ready(function ($) {

    If that does not fix it, you probably placed GetData.php in the wrong folder. You can check your access logs to see where the request was actually sent, or just specify a complete URL to the file.

    The only other thing that could be wrong is jQuery was not loaded properly, but since ItemCost is working, assuming it's on the same page, that cannot be an issue.

    I'm sure you'll get this fixed in short order. Is your form currently a WP page or a generic HTML page? If not a WP page, that should be your next challenge: Make a custom page template with working jQuery that is loaded through wp_enqueue_script().

    If you have that already, the next step is get your same PHP code working by POSTing the AJAX request through wp-admin/admin-ajax.php instead of directly to a PHP file. This will give you access to WP functions and the DB.

    Have fun! :)

  10. A31
    Member
    Posted 7 months ago #

    Hi,

    That fixed it! Thank you very much!

    As to how my pages are created, all my files are currently created when the plugin is activated, so I have full wpdb functionality on all files.

    I am puzzled though, in my GetData.php file, if I hardcode a variable:

    $Value = 'Returned Data';

    and return it with

    echo json_encode($Value);

    it returns the data perfectly, which is exactly what I want, BUT....

    the moment I run a wpdb query, it does not return it any more.

    for Example:

    global $wpdb;
    
    	$current_user = wp_get_current_user();
    	$UID = $current_user->ID;
    
       echo json_encode($UID);

    so if i view my GetData.php file on its own, I get the UID returned and displayed, however, the moment I want to pass it like I did with the hardcoded ($Value = 'Returned Data';), it does not show a value.

    Can you perhaps help where I might be missing something?

    Again thank you for your help! It is a great feeling to get something right and to know at least there are people I can ask to help me learn and get these things figured out.

    Kind Regards

  11. bcworkz
    Member
    Posted 7 months ago #

    Yes, you've run into what I've been trying to say about access to $wpdb and other WP resources. I'm not sure how to explain this, I hope it makes sense. Sorry about the length. (You should be expecting that from me by now ;) )

    You are correct in that your plugin code has access to WP resources. You kind of need to understand how WP page requests work to grasp the concept. First let's look at a normal permalink like example.com/accounts-summary/. The server executes .htaccess directives which tell it if there's no file matching the request, rewrite the request to example.com/index.php. This invokes a chain of require statements that completely load the WP environment. This includes loading your main plugin file and any files required or included by the plugin main page.

    Because the WP code base loaded your plugin file, it becomes part of the WP namespace. WP can access your functions and your functions can access WP resources. A lot more happens after plugins load, but it doesn't matter here. The point is WP called your plugin, so it becomes part of WP.

    Now let's look at your AJAX request. The PHP page is requested directly. Since this page exists on the server, the request is not rewritten to index.php and that chain of requires for loading WP does not occur. Being a PHP page, the server sends any HTML found back to the browser and executes any PHP found. In the case of your version that is not using $wpdb, all is fine. An assignment is made and JSON data is sent back to the browser.

    Now let's look at the $wpdb version. The global bit is fine, but it is only establishing a global place holder variable. No code was executed defining $wpdb. It's empty. Then there's your call get_current user(). This is a problem. No code encountered since the request has defined this function. If it happens to be on your page, no problem, the PHP interpreter will find it and use it. But there is no such thing. No function definition is encountered. The only code executed on this request was global $wpdb;.

    With no definition, PHP doesn't know how to call the function, so it throws an error and dies. The default error handler catches the error and does the default thing, which is usually logging the error to a file and then dying.

    Your AJAX query never gets a response back. After a certain period of waiting for a response, it to quietly dies. So the whole process dies without any kind of warning on the initiating page.

    You see, it's doesn't matter if WP loads your plugin which then loads your AJAX handler file, because WP is not loaded when you call the page directly. All PHP can know about on any given request is the code it encounters on the immediate page or any pages required or included from that page. Since no WP pages were included or required, no WP resources are available.

    You can't send your AJAX request to index.php either. It is expecting a certain permalink to parse. An AJAX request will just confuse it and cause a WP 404 error. I can imagine your brain's thiinking "gears" spinning right now: "Oh, oh! I can include index.php on my page and cause WP to load!"

    You would be very close, but index.php will still expect a permalink and get confused, resulting in a 404. What you could do is include wp-load.php. This bypasses the permalink expectation and loads the WP environment. This will actually work on your own installation once you figure out the correct relative reference from your plugin file to WP root where wp-load.php resides.

    The big problem with including wp-load.php is you cannot know the correct relative reference to it for any random WP installation. It's possible to completely move the plugins folder elsewhere in the file structure. So you cannot expect your plugin to work on other installations. In fact, relative references to wp-load.php alone is cause for rejection of applications for plugins to be placed on the WP repository.

    If that is not your goal, go ahead and use a relative reference if you like. For the sake of knowledge though, I encourage you to learn the "right" way to do things for future reference, even if you have no use for it right now. There are some advantages.

    The "right" way is what I've been going on about with using wp_enqueue_script() and requesting through wp-admin/admin-ajax.php. wp_enqueue_script() is good to use because it resolves all dependencies for you and ensures a compatible version of jQuery is loaded. This method will continue to work through indefinite upgrades without concern for conflicts.

    The reason for going through wp-admin/admin-ajax.php is it loads the WP environment for you without concern for where the plugin folder is relative to wp-load.php. It too will reliably work through indefinite upgrades without concern for conflicts.

    Future stability can only be relied on if you use the intended methods. Taking cheap shortcuts will not be worth it in the long run. Sooner or later they will break.

    I hope this whole AJAX thing in WP is starting to make sense now. Once you understand how to access WP resources through AJAX and establish a working data exchange, the rest will start falling into place. It should all be mostly downhill from here! There's bound to be a few humps along the way though :)

  12. A31
    Member
    Posted 7 months ago #

    Hi there,

    I have been trying to figure this out thos past few days but I am somewhere not understanding something,

    I am using the enqueue_scripts to access the admin-ajax.php

    wp_enqueue_script('custom-script1', plugin_dir_url(__FILE__) . 'js/ajax.js', array('jquery'));
    wp_localize_script('custom-script1', 'custom-script_vars1', array('ajaxurl' => admin_url('admin-ajax.php')));

    Am I missing something completely?

    Kind Regards

  13. bcworkz
    Member
    Posted 7 months ago #

    That bit looks totally fine. It's OK as is, but I would suggest changing 'ajaxurl' to something slightly different, as there is a global javascript variable of the exact same name. They are referenced differently, so there's nothing technically wrong. It's just that it can lead to confusion.

    Maybe you've done this, the code does need to be inside a declared function. That function must be added as a callback to the correct action. The action depends on where your form is presented. Use 'wp_enqueue_scripts' for front end forms, 'admin_enqueue_scripts' for backend, and 'login_enqueue_scripts' for the login form.

    You can confirm it is working by finding the link tag referring to your JS file in the head section when viewing page source. The localized data shows up in a <![CDATA[ ]]> section.

    There's two other places where things can go wrong if your AJAX is not working. One is the jQuery. Are you referencing custom-script_vars1.ajaxurl correctly? Providing an action value in the POST request? Check your error console for stray syntax errors.

    The other is the PHP AJAX handler. Have you hooked the correct action? Which one depends if the user is logged in or not. Typically front end scripts must hook both if the form is available publicly, since a logged in user could be using it just as a non-logged in user would.

    Getting the bugs ironed out of virgin script can be a challenge. Once you've gotten it working, it makes a good foundation to build upon and should give you little trouble in the future. Hang in there!

  14. A31
    Member
    Posted 7 months ago #

    Hi,

    Ok, Im going to paste ALL the code for all the files (I appologize for so much code, but i dont know what else), maybe you can spot my mistake :-(

    Plugin main FILE - AJAXTest.php

    <?php
    /*
    Plugin Name: Ajax Test
    Plugin URI: http://www.example.co.za/
    Description: Testing Ajax
    Author: Adrian Beyers
    Version: 1.0
    Author URI: http://www.example.co.za/
    */
    
    /***************************
    * GLOBAL VARIABLES
    ***************************/
    
    if (!isset($wpdb)) $wpdb = $GLOBALS['wpdb'];
    global $wpdb;
    
    /***************************
    * INCLUDES
    ***************************/
    include ("inc/setup_addPages.php");
    include ("inc/setup_shortcodes.php");
    
    /***************************
    * SETUP
    ***************************/
    
    register_activation_hook(__FILE__,'AT_Func_addTestPage');
    register_deactivation_hook(__FILE__,'AT_Func_removeTestPage');
    
    register_activation_hook(__FILE__,'AT_Func_addMyData');
    register_deactivation_hook(__FILE__,'AT_Func_removeMyData');
    
    /***************************
    * SCRIPTS
    ***************************/
    
    function AT_load_scripts() {
    	wp_enqueue_script('custom-script1', plugin_dir_url(__FILE__) . 'js/ajax.js', array('jquery'));
    	wp_enqueue_script('custom-script2', plugin_dir_url(__FILE__) . 'js/jquery.validate.js', array('jquery'));
    	wp_enqueue_script('custom-script3', plugin_dir_url(__FILE__) . 'js/jquery-1.9.1.js', array('jquery'));
    	wp_enqueue_script('custom-script4', plugin_dir_url(__FILE__) . 'js/jquery.min.js', array('jquery'));
    	wp_enqueue_script('custom-script5', plugin_dir_url(__FILE__) . 'js/jquery.validate.min.js', array('jquery'));
    	wp_enqueue_script('custom-script6', plugin_dir_url(__FILE__) . 'js/additional-methods.js', array('jquery'));
    
    	wp_enqueue_script('jquery');
    
    	wp_localize_script('custom-script1', 'custom-script_vars1', array('ajaxurl' =>  admin_url('admin-ajax.php')));
    	wp_localize_script('custom-script2', 'custom-script_vars2', array('ajaxurl' =>  admin_url('admin-ajax.php')));
    	wp_localize_script('custom-script3', 'custom-script_vars3', array('ajaxurl' =>  admin_url('admin-ajax.php')));
    	wp_localize_script('custom-script4', 'custom-script_vars4', array('ajaxurl' =>  admin_url('admin-ajax.php')));
    	wp_localize_script('custom-script5', 'custom-script_vars5', array('ajaxurl' =>  admin_url('admin-ajax.php')));
    	wp_localize_script('custom-script6', 'custom-script_vars6', array('ajaxurl' =>  admin_url('admin-ajax.php')));
    
    }
    add_action('wp_enqueue_scripts', 'AT_load_scripts');

    FILE setup_addPages.php:

    <?php
    global $wpdb;
    
    /***************************
    * SETUP PAGES
    ***************************/
    
    function AT_Func_addTestPage()
    {
    	$PageTitle = 'AJAX Test';
    	$PageContent = '[AT_TestPage]';
    	$PageStatus = 'publish';
    	$PostType = 'page';
    	$PostAuthor = 1;
    	$CommentStatus = 'closed';
    
    	$myPage = array(
    	'post_title' => $PageTitle,
    	'post_content' => $PageContent,
    	'post_status' => $PageStatus,
    	'post_type' => $PostType,
    	'post_author' => $PostAuthor,
    	'comment_status' => $CommentStatus
    	);
    
    	$post_id = wp_insert_post($myPage);
    }
    
    function AT_Func_removeTestPage()
    {
    	global $wpdb;
    	$post_tbl = $wpdb->prefix . "posts";
    	$postmeta_tbl = $wpdb->prefix . "postmeta";
    	$PageTitle = 'AJAX Test';
    	$page = get_page_by_title($PageTitle);
    	$myID = $page->ID;
    
    	$myMetaID = $wpdb->get_var($wpdb->prepare("SELECT post_id FROM em_postmeta WHERE meta_value = ".$myID.""));
    
    	$deletePost = "DELETE FROM " . $post_tbl . " WHERE ID = ".$myID."";
    	$deletePostSubs = "DELETE FROM " . $post_tbl . " WHERE post_parent = ".$myID."";
    	$deletePostMetaLink = "DELETE FROM " . $post_tbl . " WHERE ID = ".$myMetaID."";
    	$deletePostMeta = "DELETE FROM " . $postmeta_tbl . " WHERE post_id = ".$myMetaID."";
    
    	$wpdb->query($deletePost);
    	$wpdb->query($deletePostSubs);
    	$wpdb->query($deletePostMetaLink);
    	$wpdb->query($deletePostMeta);
    
    }
    
    /************************************************************************************************************/
    /************************************************************************************************************/
    /************************************************************************************************************/
    /************************************************************************************************************/
    /************************************************************************************************************/
    function AT_Func_addMyData()
    {
    	$PageTitle = 'MyData';
    	$PageContent = '[AT_MyData]';
    	$PageStatus = 'publish';
    	$PostType = 'page';
    	$PostAuthor = 1;
    	$CommentStatus = 'closed';
    
    	$myPage = array(
    	'post_title' => $PageTitle,
    	'post_content' => $PageContent,
    	'post_status' => $PageStatus,
    	'post_type' => $PostType,
    	'post_author' => $PostAuthor,
    	'comment_status' => $CommentStatus
    	);
    
    	$post_id = wp_insert_post($myPage);
    }
    
    function AT_Func_removeMyData()
    {
    	global $wpdb;
    	$post_tbl = $wpdb->prefix . "posts";
    	$postmeta_tbl = $wpdb->prefix . "postmeta";
    	$PageTitle = 'MyData';
    	$page = get_page_by_title($PageTitle);
    	$myID = $page->ID;
    
    	$myMetaID = $wpdb->get_var($wpdb->prepare("SELECT post_id FROM em_postmeta WHERE meta_value = ".$myID.""));
    
    	$deletePost = "DELETE FROM " . $post_tbl . " WHERE ID = ".$myID."";
    	$deletePostSubs = "DELETE FROM " . $post_tbl . " WHERE post_parent = ".$myID."";
    	$deletePostMetaLink = "DELETE FROM " . $post_tbl . " WHERE ID = ".$myMetaID."";
    	$deletePostMeta = "DELETE FROM " . $postmeta_tbl . " WHERE post_id = ".$myMetaID."";
    
    	$wpdb->query($deletePost);
    	$wpdb->query($deletePostSubs);
    	$wpdb->query($deletePostMetaLink);
    	$wpdb->query($deletePostMeta);
    
    }
    
    /************************************************************************************************************/
    /************************************************************************************************************/
    /************************************************************************************************************/
    /************************************************************************************************************/
    /************************************************************************************************************/

    FILE setup_shortcodes.php:

    <?php
    
    global $wpdb;
    
    /***************************
    * SETUP FRONT-END SHORTCODES
    ***************************/
    
    add_shortcode("AT_TestPage","AT_TestPage_Shortcode");
    
    function AT_TestPage_Shortcode($atts)
    {
    	  include ('TestPage.php');
    }
    
    add_shortcode("AT_MyData","AT_MyData_Shortcode");
    
    function AT_MyData_Shortcode($atts)
    {
    	  include ('MyData.php');
    }

    FILE TestPage.php:

    <div id="responsecontainer"></div>
    
    <form id="MyForm" method="post" action="" novalidate="novalidate" enctype="multipart/form-data">
    
        		<div class="FormLabel">Description</div>
                        <textarea name="Description" id="Description" width="300px"/></textarea>
    
                        <br /><br />
    
                    <div class="FormLabel">Item Cost</div>
                        <input name="ItemCost" id="ItemCost" type="text"/>
                    <div class="FormLabel">Available Budget: Rxxxx.xx (Not yet available)</div>
                    <br /><br /><br /><br />
    
                    <div class="FormLabel">Select Cost Center</div>
                        <select name="Sel_CostCentre" id="Sel_CostCentre">
                            <option value="">Please Select... </option>
                            <option value="29 Degrees">29 Degrees</option>
                            <option value="J-Zone">J-Zone</option>
                        </select>
                        <br /><br />                
    
                    <div class="FormLabel">Select Allocation Account</div>
                        <select name="txtHint" id="txtHint" required="required"></select>
                        <br /><br />                   
    
        <input type="submit" name="submit" value="Submit" />
    </form>
    
    <div id="returneddata"></div>

    FILE ajax.js:

    jQuery(document).ready(function ($) {
    
    	$("#Sel_CostCentre").change(function() {
    
    		var SendData = document.getElementById('Sel_CostCentre').value;
    		var Usernaam = "Adrian";
    
    		$.ajax({
                   type:"POST",
                    url: "http://localhost/WPTest/wp-content/plugins/AJAXTest/inc/MyData.php",
    				//data:"SentData="+SendData,
    				data: { SentData: SendData, userid: Usernaam },
                   datatype: "json",
                    success: function(data, textStatus, xhr) {
                       data = JSON.parse(xhr.responseText);
                       // do something with data
    				   $("#responsecontainer").html(data);
    				}
                });
    
    	//$("#responsecontainer").html($("#Sel_CostCentre").val());
    
    	});
    
    	$("#ItemCost").change(function()
    	{
    		$("#responsecontainer").html($("#ItemCost").val());
    	});
    
        $('#MyForm').validate({ // initialize the plugin
            rules:
    		{
                Description: {
                    required: true
                },
                ItemCost: {
                    required: true
                }
            },
    		messages:
    			{
    				Description: "Please enter a description",
    				ItemCost: "Please enter a description"
    			}
        });
    
    });
    
    	function checkValue(element)
    		{
        		if(element.value >= 2500)
    				{
            			alert ('More than 2500');
        			}
    			else if (element.value < 2500)
    				{
    					alert ('Less than 2500');
    				}
    		}

    FILE MyData.php:

    <?php
    
    	global $wpdb;
    
    	$SentData = $_POST['SentData'];
    	$userid = $_POST['userid'];
    
    	//echo json_encode($userid . " sent the following data: " . $SentData);
    
    	$Returned = $wpdb->get_var( "SELECT meta_value FROM wp_usermeta WHERE meta_key = 'ActiveEntity'" );
    	echo json_encode($Returned);

    Ok I think thats everything....

    As mentioned in my previous posts, I realise that there are some very simple queries in the MyData.php file, and that I have not added Nonces, etc. but for now I just need to get my main issue working, then I will add all the rest in my main plugin.

    The ultimate goal, is that when the user selected the value from the first select box, it should populate the second selectbox with options from a database.

    Although my code does not request that at this moment, it is supposed to return the basic query, the meta_value for a unique key from the table into a div container named "responsecontainer".

    Hopefully you can help :-( I am getting a bit discouraged after a month of trying to get this working :-(

    Thank you so much for all your help!! I really do appreciate it so much!

  15. bcworkz
    Member
    Posted 7 months ago #

    One problem may be a script conflict. You are loading jquery-1.9.1.js with the WP default 1.10.2 as a dependency. There's no need to specifically enqueue the actual jQuery file. Simply specifying it as a dependency is all you need to do. If you must use a specific version for some reason, the WP version must be deregistered. You don't want to go down that path unless you know what you're doing.

    You may not need to enqueue some of the other library files either. Check against this list. If there's a match, simply specify the handle as a dependency of your script file that's using the library. If you need the .js file on the list and it's not a dependent, simply enqueue by the handle alone: wp_enqueue_script('colorpicker');

    In general, all of this introduces potential for difficult to find conflicts. You need to develop a working AJAX exchange in isolation. Not only to obtain your own specific functional template for future use, but for study so you can truly understand what's going on and are not merely cutting and pasting code.

    For your own sanity please set this aside and focus on a very basic AJAX exchange through WP. Once you understand how this really works, then you can import it into your main project. It's the only way you can be sure the reason it is not working is a conflict and not a simple coding error. You've done this with non-WP AJAX, but I've not seen any functional WP AJAX exchange from you yet.

    The other things I'm seeing wrong is, one, your AJAX request is not being sent to the URL using the localized variable. The request must include an 'action' value to use in constructing an action hook tag.

    I'm also not seeing any handler function hooked to this tag. It can't work without an 'action' value, but I don't even see an attempt to hook something. None of this is optional, it must be part of a successful WP AJAX exchange. I must admit, I didn't study everything really closely, so I may have simply missed this.

    I'm sorry this is such a struggle for you. All I can offer is this is an important technique to master. It will continue to be a very useful skill in your future projects.

    BTW, if you need to post a lot of code, use pastebin.com and simply provide a link here. If you select the appropriate syntax highlighting when you post the code, it makes the code MUCH easier to read. It helps me help you :)

  16. A31
    Member
    Posted 7 months ago #

    Hi there,

    Thank you very much for your feedback. I have a couple of questions on what you mentioned though.
    You mention that my AJAX request is not being sent to the URL using the localized variable, is this not what you are referring to:

    wp_localize_script('custom-script1', 'custom-script_vars1', array('ajaxurl' =>  admin_url('admin-ajax.php')));

    then you also mention that you do not see any handler function hooked, I thought that my AT_load_scripts() function with
    add_action('wp_enqueue_scripts', 'AT_load_scripts'); was actually that, if not, can you please explain?

    Thank you very much for helping me figure this out.

    Kind Regards

  17. A31
    Member
    Posted 7 months ago #

    I have installed Firebug to help me troubleshoot, and the error I get is:

    SyntaxError: JSON.parse: unexpected character

    data = JSON.parse(xhr.responseText);

    Does that help?

  18. A31
    Member
    Posted 7 months ago #

    I have managed to trace one error in the jQuery code:

    success: function(data) {
               //data = JSON.parse(xhr.responseText); //WRONG CODE
    	   $("#responsecontainer").html(data); // RIGHT CODE

    so now that error is sorted, but I get the following:

    Fatal error: Call to undefined function wp_get_current_user() in C:\xampp\htdocs\WPTest\wp-content\plugins\NewAjaxTry\inc\MyData.php on line 11

    I presume this is the part that you are referring to that I have not yet linked / hooked / enqueued the needed files.

    But I still have no idea where I am missing that...

    Any advice?

  19. bcworkz
    Member
    Posted 7 months ago #

    I'm glad you resolved the jQuery error, it's not something I have a lot of experience with. I see now why you are confused, it's a natural mistake for a novice. I'm not so sure how to make it more clear, but here goes...

    First the URL for the destination of the AJAX request. When you use wp_localize_script(), you are merely defining a global javascript object that contains useful data. There are only a couple ways to pass dynamic data from PHP to javascript, this is one of them. This function sets up the data, making it available to javascript. It does not actually use the data. That is javascript/jQuery's job.

    Where you want to make use of the data is where you tell jQuery where to send the AJAX request, in this part:

    $.ajax({
       type:"POST",
       url: "http://localhost/WPTest/wp-content/plugins/AJAXTest/inc/MyData.php",

    This is the crux of why all of this is even necessary. You cannot send a request directly to MyData.php, which is what you are trying to do. Every request starts a new process thread. Each new thread is in isolation, what ever happened in a different thread has no bearing on this thread. Even though MyData.php was loaded as part of your plugin in another thread, it has nothing to do with this request. We're starting over. Thus, none of the WP functions have been defined. This is why you are getting function not defined errors.

    By sending the request to the URL that was setup in wp_localize_script() you are causing WP to load itself on your behalf. In doing so, MyData.php can again be part of your plugin, gaining access to all WP resources.

    So, to use the localized value as the URL value in the ajax call, you just use the object name, dot, property name like so:
    url: custom-script_vars1.ajaxurl,

    And don't forget to provide an 'action' value as part of the data passed in the AJAX call. It is used to construct an action tag name your PHP script hooks to.

    So now the AJAX handler callback function. wp_enqueue_script() has nothing to do with this. When we enqueue scripts, we are referring to javascript and jquery. All that enqueuing does is cause the correct .js files to be referenced in the page's head section. While it is PHP script itself, it doesn't have anything to do with other PHP script.

    In order for your AJAX handler to be used when a request is received, it must be hooked into the right action tag. The tag is composed by appending your 'action' property passed in the AJAX request to one of the prefixes determined by the context, login page, user logged in, or user not logged in. This is how admin-ajax.php routes the request to the proper handler function.

    I hope this all is starting to make sense. The whole thing is rather complex and difficult to grasp at first. After a while, you'll see it's really not so difficult. At it's most abstract, the browser sends a request and the server responds. That's it. Everything else are just setup measures to enable this to happen. No element by itself is that difficult, it's just that there are a lot of them that all need to happen. It's easy to feel overwhelmed. Try to just focus on what any one thing does at one time. Go through a list and be sure you've done each thing, and they will then all come together on their own accord.

  20. A31
    Member
    Posted 5 months ago #

    Ok, so I KNOW this has been such a long struggle for me, I finally got something right!!

    I am posting it here so that HOPEFULLY the next person won’t have to struggle so much as what I did.

    Please note that this is a VERY minimalistic approach, nothing has been properly escaped / validated or is secure.

    It really is only to demonstrate how I managed after more than 3 months to get AJAX working:

    Let’s start with the main plugin file:

    <?php
    /*
    Plugin Name: AJAX Multiple Selectbox
    Plugin URI: http://www.tigita.co.za/
    Description: AJAX Multiple Selectbox
    Author: Adrian Beyers
    Version: 1.0
    Author URI: http://www.tigita.co.za/
    */
    
    /***************************
    * GLOBAL VARIABLES
    ***************************/
    
    if (!isset($wpdb)) $wpdb = $GLOBALS['wpdb'];
    global $wpdb;
    
    /***************************
    * SCRIPTS
    ***************************/
    
    function ASB_load_scripts()
    {	
    
    	//Include Javascript library
    	wp_enqueue_script("jquery");
    	wp_enqueue_script("sack");
    
    	wp_enqueue_script('ASB_jQuery', plugins_url( '/js/myScripts.js' , __FILE__ ) , array( 'jquery' ));
    
    	// including ajax script in the plugin Myajax.ajaxurl
    	wp_localize_script( 'ASB_jQuery', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php')));
    }
    add_action('wp_enqueue_scripts', 'ASB_load_scripts');
    add_action( 'admin_enqueue_scripts', 'ASB_load_scripts');
    
    /***************************
    * INCLUDES
    ***************************/
    
    include ('inc/setup_addPages.php');
    include ('inc/setup_shortcodes.php');
    include ("inc/setup_addFunctions.php");
    
    /***************************
    * REGISTER PAGES
    ***************************/
    
    register_activation_hook(__FILE__,'ASB_Func_addPage');
    register_deactivation_hook(__FILE__,'ASB_Func_removePage');

    Next the setup_addFunctions.php:

    <?php
    
    //*******************************************************************************************************************************************
    	function form_SelectBoxExample()
    	{
    		echo 	'
    					<form id="AddNewSubject_Form" onsubmit="return false;">
    
    						<p>
    							<label>Select Option 1: </label>
    							<select class="" name="sel_Option1" id="sel_Option1" required="required">
    								<option value="">Please Select... </option>
    								<option value="Ford">Ford</option>
    								<option value="Mercedes">Mercedes</option>
    							</select>
    						</p>
    						<p>
    							<label>Select Option 2: </label>
    							<select class="" name="sel_Option2" id="sel_Option2" required="required">
    								<option value="">Please Select... </option>
    							</select>
    						</p>
    					</form>
    				';
    	}
    	add_action('SelectBoxExample_Form', 'form_SelectBoxExample');
    
    //*******************************************************************************************************************************************
    
    //*******************************************************************************************************************************************
    
    	function ASB_func_GetOption2()
    	{
    		global $wpdb;
    
    		if (isset($_POST['SelectedOption1']))
    		{
    			$Option1 = $_POST['SelectedOption1'];
    
    			$SQL_Query = 	("SELECT Option2 FROM customOptions_tbl WHERE Option1 = '" . $Option1 . "'");
    			$SQL_Result = $wpdb->get_results($SQL_Query);
    
    			foreach($SQL_Result as $mySQL_Result)
    			{
    				$Option2 = $mySQL_Result->Option2;
    				echo '<option value=' . $Option2 . '>' . $Option2 . '</option>';
    			}
    
    		}
    
    		die();
    		return true;
    	}
    	add_action('wp_ajax_ASB_func_GetOption2', 'ASB_func_GetOption2');
    	add_action('wp_ajax_nopriv_ASB_func_GetOption2', 'ASB_func_GetOption2');
    
    //*******************************************************************************************************************************************
    ?>

    Now the myScript.js:

    // JavaScript Document
    
    jQuery(document).ready(function ($)
    {
    	jQuery('#sel_Option1').change(function()
    	{
    		var SelectedOption1 = jQuery("#sel_Option1").val();
    
    		jQuery.ajax(
    		{
    			type: 'POST',
    			url: MyAjax.ajaxurl,
    			data: 	{
    						"action": "ASB_func_GetOption2",
    						"SelectedOption1": SelectedOption1
    					},
    			success: function(data)
    			{
    				jQuery('#sel_Option2').html(data);
    			}
    		});
    	});
    });

    setup_shortcodes.php:

    <?php
    
    	global $wpdb;
    
    	/***************************
    	* SETUP FRONT-END SHORTCODES
    	***************************/
    
    	add_shortcode("ASB_MultiSelect","ASB_MultiSelect_Shortcode");
    
    	function ASB_MultiSelect_Shortcode($atts)
    	{
    		  include ('MultiSelect.php');
    	}
    
    ?>

    And lastly MultiSelect.php:

    <?php
    
    	do_action('SelectBoxExample_Form');

    I REALLY hope that this helps someone else!

  21. A31
    Member
    Posted 5 months ago #

    Thnx to bcworkz for all your help!!

  22. bcworkz
    Member
    Posted 5 months ago #

    You are most welcome! You must be truly elated to finally conquer this!

    Isn't it ironic that after so much struggle, the final code is fairly simple? If it helps any, I too struggled at first to get AJAX working, many silly errors because I didn't understand what was going on. But by struggling through it all, I learned a lot. It was worth the struggle for me. Maybe not right now, but I think you will eventually feel the same.

Reply

You must log in to post.

About this Topic