0

Consider the following example: we build a conference website (could be a WordCamp) that allows speakers to submits talks, and where a jury decides which talks are accepted.

To handle this in WordPress, we simply use:

  • a "talk" custom post type
  • a "talk-status" taxonomy, with the terms "accepted" / "rejected".

The next step is to build an admin view on the frontend that lists all pending talks (that’s the easy part), and offers action buttons to accept or reject a talk (that’s the less easy part).

Here's a mockup of that page:

enter image description here

What should happen when the jury user clicks on "accept"?

A function similar to that should get executed:

<?php 
wp_set_object_terms( 
  $talk_id, // ID of the selected talk, submitted by form
  $talk_status, // term: "accepted", submitted by form
  'talk-status', // $taxonomy, 
  false // $append 
);

What it does: it attaches the term "accepted" (from the "talk-status" taxonomy) to the selected talk.

Now, the question: how to trigger such a function from a form button, and how to pass our two values ($talk_id, $talk_status) to the function?

I would like to get to the most simple working example. I'm aware that there are some similar questions already... but I think it would be useful to have another clear and simple example, using standard WordPress methods as of late 2015.

2
  • 1
    I suggest reading AJAX in Plugins. The method for making AJAX requests hasn't changed since its introduction many versions ago. You're more likely to get help if you show some effort to solve this and present specific issues in your implementation.
    – Milo
    Commented Dec 17, 2015 at 21:16
  • Thanks Milo for the advice, I will certainly give it a try and add my findings to this page.
    – Manu
    Commented Dec 17, 2015 at 22:30

1 Answer 1

1

This is a simple example of rendering some items on the front-end that use AJAX to trigger changes in the back-end and update the UI from that response.

There are other examples that enqueue scripts so just read up on AJAX and consider this a high level view.

REGISTER AJAX/SCRIPTS/CSS

add_action('init', function () {

    // Register AJAX handlers

    add_action('wp_ajax_set_pending_item_state', 'set_pending_item_state');
    add_action('wp_ajax_nopriv_set_pending_item_state', 'set_pending_item_state');

    // AJAX handler (PRIV / NO PRIV)

    function set_pending_item_state()
    {
        if( empty ($_POST['action']) || $_POST['action'] !== 'set_pending_item_state') {
            if (!empty ($fail_message)) {
                wp_send_json_error(array(
                    'message' => "Sorry!"
                )); // die
            }
        }

        $id = $_POST['id'];
        $state = $_POST['state'];

        wp_send_json_success(array(
            'action' => $_POST['action'],
            'message' => 'State Was Set To ' . $state,
            'state' => $state,
            'ID' => $id
        )); // die
    }
});

add_action('wp_footer', function () { ?>

    <style>
        .pending-form,
        .pending-list,
        .pending-list-item {
            display: block;
            color:grey;
        }

        .pending-accept {
            color:green;
        }
        .pending-reject {
            color:red;
        }

        .pending-list-item[data-state="0"] {
            color:inherit;
        }
        .pending-list-item[data-state="-1"] .title {
            color:red;
        }
        .pending-list-item[data-state="1"] .title {
            color:green;
        }
    </style>
    <script>
        (function ($) {

            var $form = $('.pending-form'),
                $item = $form.find( '.pending-list-item');

            // Trigger to make AJAX call to set state for ID
            // ( 1:accept, -1:reject )
            function setState(id, state) {

                // item clicked
                var $item = $('.pending-list-item[data-id="' + id + '"]'),

                // gather data
                    data = {
                        action: 'set_pending_item_state',
                        id:      id,
                        state:   state
                    };

                // make AJAX POST call    
                $.ajax({
                    type: 'POST',
                    url: ajaxurl,
                    data: data,
                    success: function (response) {

                        // look at the response

                        if (response.success) {

                            // update the UI to reflect the response
                            $item.attr ('data-state', state);

                            // succcess data
                            console.log(response.data);

                        } else {

                            // no good
                            console.log(response);
                        }
                    }
                });
            }

            // setup the items
            $item.each (function (inx, item){

                var $item = jQuery(item),
                    $acceptBtn = $item.find ('.pending-accept'),
                    $rejectBtn = $item.find ('.pending-reject');

                // setup the button click handlers

                $acceptBtn.on ('click', function(){
                    var id = $item.attr ('data-id');
                    setState( id, 1);
                });

                $rejectBtn.on ('click', function(){
                    var id = $item.attr ('data-id');
                    setState( id, -1);
                });
            });

        })(jQuery);
    </script>
<?php });

RENDER FORM

<div class="pending-form">
<?php
    $pending_talk_list = array(
        array( 'id' => '313',  'title'=> 'This is a title1', 'speaker' => 'some person1', 'abstract' => '12sdlfjskdfjsdfl', 'state' => 0),
        array( 'id' => '252',  'title'=> 'This is a title2', 'speaker' => 'some person1', 'abstract' => '23sdlfjskdfjsdfl', 'state' => 0),
        array( 'id' => '344',  'title'=> 'This is a title3', 'speaker' => 'some person2', 'abstract' => '45sdlfjskdfjsdfl', 'state' => 0),
        array( 'id' => '421',  'title'=> 'This is a title4', 'speaker' => 'some person3', 'abstract' => '67sdlfjskdfjsdfl', 'state' => 0),
    );

    echo "<h1>Pending Talks</h1>";

    echo "<ul class='pending-list'>"; // pending list

    foreach($pending_talk_list as $inx => $talk ) {

        $title = $talk['title'];
        $speaker = $talk['speaker'];
        $abstract = $talk['abstract'];
        $state = $talk['state'];
        $id = $talk['id'];

        echo "<li class='pending-list-item' data-state='{$state}' data-id='{$id}'><div class='title'>{$title}</div><div class='speaker'>{$speaker}</div><div class='abstract'>{$abstract}</div><a class='pending-accept'>accept</a><a class='pending-reject'>reject</a></li>";
    }

    echo "</ul>"; // end pending list
?>
</div>
3
  • Thanks a lot for the code, I'm trying to implement it. Will report back.
    – Manu
    Commented Dec 18, 2015 at 20:27
  • Awesome, it's working great! One thing I had to change in your sample code, was to define ajaxurl, otherwise I would get "ajaxurl is not defined"... So I added var ajaxurl = "<?php echo admin_url('admin-ajax.php'); ?>"; to the beginning of the javascript code.
    – Manu
    Commented Dec 19, 2015 at 22:39
  • If you're making this for realz, check out codex.wordpress.org/Function_Reference/wp_localize_script where you can add a bunch of js variables before a script prints. Super useful for many reasons. Enjoy!
    – jgraup
    Commented Dec 19, 2015 at 22:42

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.