How to link Wordpress heartbeat to ajax form

I have a form that $_POSTs an input value, and user's ID that saves the data to the database:

// frontend form 
form id="form"
    input type="radio" name="location" id="name1" value="1"
    label for="name1"Label 1/label

    input type="radio" name="location" id="name2" value="2"
    label for="name2"Label 2/label

    input type="radio" name="location" id="name3" value="3"
    label for="name3"Label 3/label

    input type="hidden" name="userid" value="{userid}"
/form     


// footer script
script
$(function() {
    $( "#form" ).change(function(a) {
        a.preventDefault();
        var formdata = new FormData($(this)[0]);

        $.ajax({
            method:         "POST",
            data:           formdata,
            contentType:    false,
            processData:    false
        });
    });
});
/script


// validation snippet
?php
    $location = isset( $_POST['location'] ) ? $_POST['location'] : '';
    $userID   = isset( $_POST['userid']   ) ? $_POST['userid']   : '';
    update_user_meta( $userID, 'location_current',  $location );
?

When the users sets the radio location from their desktop, it send the form to the server, and saves it.

Each user also has a display (tablet) that has no input but echoes out the location value.

I currently have the tablet refreshing every 5 minutes, but wanted it to be more of a push with WP heartbeat.

I tried using this example: https://gist.github.com/strangerstudios/5888123

But wasnt sure how to have the value of the data['client'] = 'marco'; be data['client'] = '?= $_POST['location']; ?'; each time as it is printed once and not refreshed once the page is loaded or the location changed.

Topic heartbeat-api front-end ajax jquery forms Wordpress

Category Web


Saving data

Based on Heartbeat API, you can add custom data to the sent heartbeat on heartbeat-send event in js. This would be used instead of the ajax function you have in your code example.

jQuery( document ).on( 'heartbeat-send', function ( event, data ) {
  // Grab the required form data
  data.location = jQuery('input[name="location"]:checked').val();
  data.userid = jQuery('input[name="userid"]').val();
});

You can then use the data in PHP with hearbeat_recieved filter. There's also the heartbeat_nopriv_received filter for no-privilege environments.

add_filter( 'heartbeat_received', 'myplugin_save_location_on_heartbeat', 10, 2 );
function myplugin_save_location_on_heartbeat( $response, $data ) {
  // data required
  if ( empty( $data['location'] ) || empty( $data['userid'] ) ) {
    return $response;
  }
  // validate
  if ( ! is_numeric( $data['location'] ) || ! is_numeric( $data['userid'] ) ) {
    return $response;
  }
  // sanitize
  $location = absint( $data['location'] );
  $userID = absint( $data['userid'] );
  // update
  update_user_meta( $userID, 'location_current',  $location );
  // optional response
  $send_data_back = true;
  if ( $send_data_back ) {
    $response['location'] = $location;
    $response['userid'] = $userID;
  }
  // send response
  return $response;
}

You can access the data (response from hearbeat_recieved) again on heartbeat-tick event in js,

jQuery( document ).on( 'heartbeat-tick', function ( event, data ) {
  // Check for our data, and use it.
  if ( ! data.location || ! data.userid ) {
    return;
  }
  // use the response as needed
  console.log("location: " + data.location);
  console.log("user: " + data.userid);
});

Get data

With couple of tweaks you can get just the location data instead of saving it.

First send user id with heartbeat-send in js,

jQuery( document ).on( 'heartbeat-send', function ( event, data ) {
  data.userid = jQuery('input[name="userid"]').val();
});

Then respond with current location user meta in PHP on hearbeat_recieved,

add_filter( 'heartbeat_received', 'myplugin_get_location_on_heartbeat', 10, 2 );
function myplugin_get_location_on_heartbeat( $response, $data ) {
  // data required
  if ( empty( $data['userid'] ) ) {
    return $response;
  }
  // validate
  if ( ! is_numeric( $data['userid'] ) ) {
    return $response;
  }
  // sanitize
  $userID = absint( $data['userid'] );
  // update
  $location = get_user_meta( $userID, 'location_current',  true );
  // send response
  return $response['location'] = $location;
}

EDIT 1: I think you could also use get_current_user_id() inside the php response function to get the user id, if you don't want to or can't send it in js on heartbeat-send event.

Last, update your view with the recieved data on heartbeat-tick in js,

jQuery( document ).on( 'heartbeat-tick', function ( event, data ) {
  // Check for our data, and use it.
  if ( ! data.location ) {
    return;
  }
  // if using radio buttons
  jQuery('input[name="location"][value='"+data.location+"']').prop('checked', true);
  // if you want to show result in somewhere else
  jQuery('#location-output-element').text(data.location);
});

I hope this helps and answers your question.


To send value using HTTP methods, the page must submit data. Only page refresh will not work. Your page must send a post request with the data location and you are using ajax to send form data.

In the API data['client'] = 'marco'; you can use your own data object send from your ajax request.

data['client'] = your formdata;

or you can use your PHP code same as you mentioned above:

data['client'] = '<?php echo $_POST['location']; ?>'; // make sure you validate data first.

If this doesn't help, please show the full implementation of API and usage of your ajax data.

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.