I want to include a custom code into a page with dynamic selects. I am using code snippets plugin to write PHP. But I am stuck right now with a 400 ajax error when I try to select a value. I have been struggling with this problem for some time now and have tried a lot of things, dumbed down my code. I have read do many posts on this error code, I don't know where to look anymore...

The URL is on a test "live" website that you can find here: https://firehoff.vimaweb.fr/test/ Any help would be greatly appreciated...

add_shortcode('choix_produits', 'wpcode_elementor_shortcode');

function wpcode_elementor_shortcode($atts) {
    global $wpdb;
    $admin_url = admin_url( 'admin-ajax.php' );
    echo "<form action=\"$admin_url\" method=\"post\" class=\"\">";
    echo '<select name="marques" id="marques">';

    $results = $wpdb->get_results("SELECT distinct(marque) FROM wpfir_module_bougies;");

    if ($results) {
        foreach ($results as $row) {
            echo '<option value="' . esc_attr($row->marque) . '">' . esc_html($row->marque) . '</option>';
    } else {
        echo '<option value="">Aucune donnée trouvée</option>';
    echo '</select>';
    echo '<select name="modeles" id="modeles"><option value="">Sélectionnez un modèle</option></select>';
    echo '</form>'; 
    $nonce = wp_create_nonce('my_nonce_action');

    // Ajout du script
    wp_register_script('script_bougies', content_url() . '/plugins/bougies/script_bougies.js', array('jquery'), '1.0', true);
    wp_localize_script('script_bougies', 'ajax_object', array('ajax_url' => admin_url('admin-ajax.php'),'nonce' => $nonce));
    add_action('wp_ajax_get_modeles', 'get_modeles_callback');
    add_action('wp_ajax_nopriv_get_modeles', 'get_modeles_callback');

    function get_modeles_callback() {
        /*$marque_selected = esc_sql($_POST['marque']);
        //error_log("marque : ".print_r( $marque_selected, true ) );
        $modeles = $wpdb->get_results($wpdb->prepare("SELECT distinct(modele) FROM wpfir_module_bougies where marque = %s", $marque_selected));

        if ($modeles) {
            $options_html = '';
            foreach ($modeles as $modele) {
                $options_html .= '<option value="' . esc_attr($modele->modele) . '">' . esc_html($modele->modele) . '</option>';
        } else {
            echo "<option value=''>Aucune donnée trouvée</option>";

        echo $options_html;*/
        echo "<option value=''>test</option>";

jQuery(document).ready(function ($) { 
    $('#marques').on('change', function() {
        var marqueSelected = $(this).val();

            url: ajax_object.ajax_url,
            type: "POST",
            dataType: "json", 
            data: {
                action: "get_modeles", 
                marque: marqueSelected,
                nonce: ajax_object.nonce
            success: function(response) {
            error: function(xhr, status, error) {
                console.error(status + ': ' + error);

Edit : alright, I did some progress thanks to you, now it's working but I can only display 456 inside my select. I need to dig to see why I can't put html or $ inside the echo, for now only echo 456; works.

Edit 2 : nailed it! Thank you all for your patience, I can now work on content ;)

  • As an aside this would work as a REST endpoint instead of an admin AJAX endpoint, and I think that's the more 'modern' way of doing this. That said admin AJAX isn't going away either.
    – Rup
    Jan 17 at 9:56

1 Answer 1


You're declaring the AJAX handler inside the shortcode handler. That's not going to work: admin AJAX requests aren't processed in the context of a page, so the shortcode won't be run, so the handler won't be set up.

You'll need to move the function definition and add_actions out to the top level, not inside wpcode_elementor_shortcode.

Your script enqueues also look wrong too: they're supposed to be called from a wp_enqueue_scripts hook handler, which will be called before you know whether they're actually needed on a page - AFAIK there's no good solution to only including scripts on the right pages. That said, you might get away with that here if the script is set to be included in the footer (which it's not at first glance) and the dependencies just work out too.

  • Hi, thank you for your answer. In the link you posted, if you go a little further, he created another post in 2012 that says (if I understood correctly) it's possible to declare the handler inside the shortcode handler since Wordpress 3.3. scribu.net/wordpress/conditional-script-loading-revisited.html If not, where do I put the declaration? I tried in the function.php, but it doesn't work. Jan 17 at 13:31
  • Oh well, I managed to put it inside function.php, but I still have a 400 error. Jan 17 at 14:15
  • Huh, maybe I'm wrong then: if the script enqueuing was already working for you then great, probably fine as-is.
    – Rup
    Jan 17 at 14:16
  • However that definitely won't work for the AJAX handler which will need to be declared outside the shortcode handler.
    – Rup
    Jan 17 at 14:17
  • I also tried to put the callback inside the function.php, but when I do, it doesn't do anything when I trigger the change. Jan 17 at 14:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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