aleks1217
aleks1217

Reputation: 87

How to repeat jQuery request for each wp_query result

I am running queries in Wordpress that should return a customer's three most recent orders. When a user clicks on the "Change" button, it should open an order form with a "Save" and "Cancel" button.

My jQuery is only working on the first result of the query. When I click the "Change" button on the second and third entries, nothing happens.

I've tried doing a loop on the jQuery, but it still only applies to the first result, so I am thinking I need to attach a variable unique ID to "order_form" or request the jQuery to run three times.

Suggestions on what I should try?

function hgf_myhome_dash() {

foreach( array_combine( $menuid, $custom_field_data ) as $menuid => $custom_field_data ) {

    $user_menu = json_decode( stripcslashes( $custom_field_data ) );

// The button
    echo '<div id="change_button" style="float: left;">' .  do_shortcode('[button]Change this menu[/button]') . '</div>';


// The loop
    foreach( $user_menu as $single ){   
        if( $single->id ) { 
            echo get_post( $single->id )->post_title;
        }}

// The form
        echo '
            <div id="form_show" class="modal">
            <form id="order_form"  action="" method="POST">
            <div class="modal-content">

            <div class="col_title"><h3>'.__('Current Menu' ,'rm_domain').'</h3> 
            <input type="button" id="cancel_button" class="cancel_menu" value="Cancel" />
            <input type="submit" class="save_menu" style="" name="msubmit" id="msubmit" value="Save" />
            </div>

            I am text, hear me roar.

            </div>
            </form>
            </div>
            ';



    } 

}

And here is my jQuery:

jQuery(document).ready(function($){

$("#order_form").hide();

    $( function() {
        $( "#change_button" ).on( "click", function() {
                    $("#form_show").css('display', 'block');
             $("#order_form").show();
        });

        $( "#cancel_button" ).on( "click", function() {
                $("#form_show").css('display', 'none');
             $("#order_form").hide();
        });

      } );

}); 

Upvotes: 0

Views: 108

Answers (1)

Dzmitry Kushnarou
Dzmitry Kushnarou

Reputation: 566

The id attributes must be unique. You can’t have more than one tag with the same ID. When you have several elements with the same ID, the browser will ignore all the IDs except the first one.

So, only the first appearances of id="change_button", id="form_show", id="order_form", id="cancel_button" will be counted. Other tags will behave as if they don’t have IDs.

Instead of ID, you can use the class element, which doesn’t need to be unique, like this:

echo '<div class="change_button" style="float: left;">' .  do_shortcode('[button]Change this menu[/button]') . '</div>';

Then, you need to change your selectors: the #change_button searches for the element with id="change_button", and .change_button searches for elements with class="change_button" (you can have several classes separated by spaces, like class="some_class change_button some_other_class", and .change_button will still work).

However, there is a rub: the selector will find all the elements with this class. So, $(".form_show").css('display', 'block'); will show all the forms with class="form_show", and clicking on any button will show all the forms. Which is not what you need.

So, your code needs to know which form is clicked, and select the correct one.

You can access the button you’ve clicked with this inside the click handler. Note that this would be a DOM element and not a jQuery object. To convert it into a jQuery object, you need to use $(this).

You can use jQuery functions on $(this) to get elements around the button. For example, the .next() function will return a jQuery object containing the next element. So, you could use $(this).next().show() to show the element after .change_button (which is the form).

However, I would advise agains using .next. It makes the JavaScript too dependent on the layout. The designer might need to add some other tags between the button and the form, and then you’d need to change your code.

Instead, you can add some data into the .change_button that will allow to identify the form that needs to be opened. For example, you can assign numbers to all your forms, and add that number to the .change_button.

To add custom data to any element, you can use data-something="any data". This is HTML5 tag for adding arbitrary data. It is very handy because it can be accessed by using $(this).data('something') in jQuery.

So, you can add unique index to your buttons, and add that index to your form. You can add unique index like this:

function hgf_myhome_dash() {

$index = 1;

foreach( array_combine( $menuid, $custom_field_data ) as $menuid => $custom_field_data ) {

    $user_menu = json_decode( stripcslashes( $custom_field_data ) );

    // The button
    echo '<div class="change_button" data-index="' . $index . '" style="float: left;">' .  do_shortcode('[button]Change this menu[/button]') . '</div>';


    // The loop
    foreach( $user_menu as $single ){
        if( $single->id ) { 
            echo get_post( $single->id )->post_title;
        }
    }

    // The form
        echo '
            <div id="form_show_' . $index . '" class="modal">
            <form id="order_form_' . $index . '"  action="" method="POST">
            <div class="modal-content">

            <div class="col_title"><h3>'.__('Current Menu' ,'rm_domain').'</h3> 
            <input type="button" class="cancel_menu cancel_button" value="Cancel" />
            <input type="submit" class="save_menu" style="" name="msubmit" id="msubmit_' . $index . '" value="Save" />
            </div>

            I am text, hear me roar.

            </div>
            </form>
            </div>
            ';



    } 

    ++$index;
}

Note that I’ve used class for change_button and cancel_button (because there might be several buttons with these classes), but I’ve kept id for form_show_{INDEX}, order_form_{INDEX}. This is because, when we add index, the IDs become unique (there will be only one form_show_1, only one form_show_2 and so on in the document), so we use id and not class.

N.B. IDs must be unique, so you can only call your function hgf_myhome_dash only once per page. If you call it more than once, your JavaScript will only work correctly for the first instance. If you want to call the function many times, you can use some global variable instead of $index — but then you probably need to rename it to something longer, to avoid name clashes.

Then, you can change your JS code like this:

jQuery(document).ready(function($){

$("#order_form").hide();

    $( function() {
        $( ".change_button" ).on( "click", function() {
             var index = $(this).data('index');
             $("#form_show_" + index).css('display', 'block');
             $("#order_form_" + index).show();
        });

        $( "#cancel_button" ).on( "click", function() {
             var index = $(this).data('index');
             $("#form_show_" + index).css('display', 'none');
             $("#order_form_" + index).hide();
        });

      } );

}); 

P.S. By the way, $menuid and $custom_field_data are not defined inside your function. Since it’s not a matter of your question, I assume you’ve removed some part of the code code. If not, you probably need to make them global, or to pass them via function arguments.

Upvotes: 1

Related Questions