1

This is my first attempt to write a plugin and I get an error 400 when trying to use admin-ajax.php. I've looked through some topics both here and in the WordPress support forum, but cannot figure it out.

What I am trying to do is dependant drop-down select. I.e. you chose an option from select #1, then it has to be passed via ajax to populate the second dropdown. To make it simple (for now), everything is on my "frontend" file.

Here is my code:


        <div class="row">
            <select class="cat-select" name="lvl1" id="lvl1">
                <option value="">-- select category --</option>
                <?php
                foreach ($this->getTopLevelCategories() as $category) {
                    print '<option value="' . $category->term_id . '">' . $category->name . ' (' . $category->count . ')</option>';
                }
                ?>
            </select>
        </div>

        <script type="text/javascript">
            jQuery(document).ready(function () {
                jQuery('#lvl1').change(function () {
                    var lvl1Val = jQuery('#lvl1').val();
                    jQuery('#lvl2').empty();
                    jQuery.ajax({
                        url: "<?php bloginfo('wpurl'); ?>/wp-admin/admin-ajax.php",
                        method: 'POST',
                        data: {
                            'action':'getLVl2',
                            'lvl1' : document.getElementById('lvl1').value
                        },
                        success: function(response, status) {
                            jQuery('#lvl2').append(response);
                            alert(response);
                            console.log(response);
                        },
                        error: function(errorThrown){
                            console.log(errorThrown);
                        }
                    });
                });
            });
        </script>

        <div class="row">
            <select class="cat-select" name="lvl2" id="lvl2">
                <option value="" disabled selected>-- select category lvl2 --</option>
            </select>
        </div>

        <?php

        function getLVl2()
        {
            if (isset($_POST['lvl1'])) :

                $parent = $_POST['lvl1'];

                $option = '<option value="' . $parent . '">';
                $option .= $parent;
                $option .= '</option>';

                echo $option;

                wp_die();

            endif;
        }

        add_action('wp_ajax_getLVl2', 'getLVl2');
        add_action('wp_ajax_nopriv_getLVl2', 'getLVl2');
        ?>

Note:

  1. The code in the function will be changed. What I am trying to do is output the value of the option selected from the first dropdown just to see that it works.
  2. The function and the script will be moved to their places to "keep the code clean"
8
  • 1
    A 400 error indicates that your AJAX actions are not being registered or registered late, so generally in a theme, you should register them via the functions.php file. Did you put your getLVl2() function and add_action() code in the functions file? Also, have you considered using the REST API instead (which can give you a pretty route/path like my-plugin/v1/getLVl2)?
    – Sally CJ
    Jun 20 at 7:10
  • No, I don't have them on the template functions.php. I have them in my plugin only. As for the REST API - I've mentioned this is my first attempt to write WordPress plugin so I think it will be more complicated for me than "the usual" way.
    – milenmk
    Jun 20 at 7:13
  • As for the REST API, you would want to read this, but there are actually built-in endpoints for fetching terms in a specific taxonomy, e.g. /wp/v2/categories for the core category taxonomy. So for example, fetch( '/wp-json/wp/v2/categories' ) would let you, via JS, fetch the site's categories.
    – Sally CJ
    Jun 20 at 7:36
  • 1
    As for your plugin, where are you calling the add_action()? Is it at the root in the plugin file, e.g. <?php /* Plugin Name: My Plugin */ ... add_action( ... ); ?
    – Sally CJ
    Jun 20 at 7:39
  • 1
    If you are getting a 0, then that likely means the $_POST['lvl1'] was not set - and you just need to ensure that your JS sends the proper data. So you could just do var_dump( $_POST ); before the if block and you'd know for sure if my guess was correct.
    – Sally CJ
    Jun 20 at 7:52

1 Answer 1

1

This may not definitively answer the question, but I hope this helps you in finding the most appropriate solution. And actually, I've tried the super simple plugin at the bottom with your HTML and JS, and everything worked fine for me.

This is my first attempt to write a plugin and I get an error 400 when trying to use admin-ajax.php

These are the common reasons why would admin-ajax.php return a 400 error (or a HTTP status of "400 Bad Request") and then display a 0:

  1. Your AJAX action was never registered or it's registered late.

  2. Your JS script or AJAX request did not include the correct action value, i.e. the part after wp_ajax_ and wp_ajax_nopriv_.

  3. The current user is not logged-in and your AJAX action was registered only for logged-in users.

    Or the other way round — the user is logged-in, but your AJAX action was only for non logged-in users.

And in your case, where the AJAX action is getLVl2, the 400 error was likely due to reason #1 above, because your JS is sending the correct action and it's also registered for both logged-in and non logged-in users, i.e. you hooked on both wp_ajax_getLVl2 and wp_ajax_nopriv_getLVl2.

So you'd just need to ensure you are calling add_action() at the right time, e.g. in the main plugin file like so (which should be located at wp-content/plugins/my-plugin/my-plugin.php):

<?php
/*
 * Plugin Name: My Plugin
 */

function getLVl2() {
//  echo 'test';
    echo '<option>test</option>';
    wp_die();
}
add_action( 'wp_ajax_getLVl2', 'getLVl2' );        // for logged-in users
add_action( 'wp_ajax_nopriv_getLVl2', 'getLVl2' ); // for non logged-in users

Now try, using your browser, visiting https://example.com/wp-admin/admin-ajax.php?action=getLVl2 and check if the test is displayed on the page.

2
  • 1
    Through some testing, I've already found out that the add_action and the functions called from the ajax should be in the main plugin file. Everything works now. Thanks for your help.
    – milenmk
    Jun 21 at 6:44
  • Glad I could help :) And actually, they don't necessarily need to be in the main plugin file, so for example you can put them in external PHP file and load it via the main plugin file, e.g. require_once __DIR__ . '/path/to/your-file.php';. What's important for you to remember is that the add_action() should be called before or by the time WordPress runs the admin_init hook.
    – Sally CJ
    Jun 21 at 11:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.