Posted on by

Putting a Delete Switch in the Record Edit Form

I sometimes get requests for adding the ability to delete records from the frontend record edit interface. This is so a person with a private edit link can go to their record page and delete it, or so someone who is managing records from the frontend can delete a record.

(Note: I’ve published an updated version of this post, I suggest you get your code from that post. The code in this post won’t work as expected with the current version of Participants Database)

The best way to do it:

The easy (no code needed) and recommended way to do this is to create a checkbox field that when checked, marks the record for deletion. The actual record deletion (if that is what you want to do) takes place in the backend where an administrator can easily delete multiple records.

To prevent records that are supposed to be deleted from showing up, they can be filtered out of the list display using a shortcode filter, something like this: [pdb_list filter="delete!yes"]

The main reason this is the recommended way to implement this feature is that once a record is deleted, it’s gone forever. If there happened to be an accidental deletion, it will be nearly impossible to restore that record. Another reason is that sometimes, as a site administrator, you want to retain that data in case it’s needed in the future.

What if you really want to delete a record from the frontend?

OK, you’ve been warned of the dangers, but you really want the record deleted. This can be done, and it’s a good opportunity to show how to use one of the main filters in the plugin’s API. This tutorial assumes you know something about PHP, because you’ll need to create a function that performs the deletion. Generally, such a function goes into the theme functions.php file, but it can also be implemented as a plugin.

If you need a primer, the WordPress Codex has a a good brief explanation on the general method for using a filter: add_filter()

Using one of the plugin’s filters is exactly the same because it’s filters are added to all the WordPress filters, and work in exactly the same way. The idea is that when the plugin is going to use a value, it passes it though a filter. Normally that filter does nothing, but you can write a function to change that value. The important thing to remember about using filters is that the value (changed or not) must be returned by the function.

The Tutorial

1.

Create your “delete” switch by adding a field named “Delete Record” and then make it a checkbox field with a “yes,no” value. You may want to add a help text that says something like: “Check this box to delete your record. Warning: your record will be gone forever if you do this.”

2.

Open up your theme “functions.php” file. You should be using a child theme so you can update your theme without losing your code. We are going to add a function (called a “filter callback”) and the filter. The filter calls the function. Place this anywhere in your function.php file.

Here is your callback function:

/**
 * deletes a record from the frontend
 * 
 * @param array $post the submitted data
 * 
 * @return array|bool the unaltered array or bool false if the record 
 *                    is deleted
 */
add_filter('pdb-before_submit_update', 'xnau_frontend_delete_record');
function xnau_frontend_delete_record($post) {
  
  /* 
   * check our checkbox value; we also don't do anything if we're 
   * in the backend
   */
  if ($post['delete_record'] !== 'yes' or is_admin()) {
    // do nothing, return the data array unaltered
    return $post;
  }
  /*
   * if we get here, the delete checkbox has been checked, so delete 
   * the record from the database
   */
  global $wpdb;
  $sql = 'DELETE FROM ' . Participants_Db::$participants_table . ' WHERE `id` = "%d"';
  $wpdb->query($wpdb->prepare($sql, $post['id']));
  
  // return with false so that the record isn't saved
  return false;
}

3.

The first thing we do here is check the the state of our record delete checkbox. If it’s unchecked, we return the $post array unaltered.

The ‘pdb-before_submit_update’ filter is fired on every record edit submission both on the backend and the frontend. We also check to make sure we are not in the admin so there won’t be an accidental deletion in that context.

If the checkbox is checked, we get right to deleting the record using a standard WordPress database method. Take a look at the documentation for the $wpdb class if you’re interested in knowing the details of how that is used.

4.

When the user submits the form with the delete checkbox checked, the record is deleted, and they are returned to the record edit page. The record doesn’t exist anymore, so the “no record found” message is shown. To give the user the specific feedback that their record was deleted, we can add that by altering the global “Record Not Found Error Message” setting like this:

Participants_Db::$plugin_options['no_record_error_message'] = __('The record has been deleted.');

Here is the complete function:

/**
 * deletes a record from the frontend
 * 
 * @param array $post the submitted data
 * 
 * @return array|bool the unaltered array or bool false if the record 
 *                    is deleted
 */
add_filter('pdb-before_submit_update', 'xnau_frontend_delete_record');
function xnau_frontend_delete_record($post) {
  
  /* 
   * check our checkbox value; we also don't do anything if we're 
   * in the backend
   */
  if ($post['delete_record'] !== 'yes' or is_admin()) {
    // do nothing, return the data array unaltered
    return $post;
  }
  /*
   * if we get here, the delete checkbox has been checked, so delete 
   * the record from the database
   */
  global $wpdb;
  $sql = 'DELETE FROM ' . Participants_Db::$participants_table . ' WHERE `id` = "%d"';
  $wpdb->query($wpdb->prepare($sql, $post['id']));
  
  /*
   * set up the user feedback message
   * 
   * this simply replaces the global message setting with a new message
   */
  Participants_Db::$plugin_options['no_record_error_message'] = __('The record has been deleted.');
  
  // return with false so that the record isn't saved
  return false;
}

5.

It might be a good idea to give the user a chance to confirm the record deletion before it’s committed. This is best done using a Javascript modal dialog. That is beyond what I’m covering here, but the general way to do this is to use a custom template for your record edit shortcode, then add the javascript to that template.

An easy way to generate the modal dialog is using jQuery UI Dialog. A web search for “jquery ui dialog confirm submission” will help you find code you can use to add that feature.

10 thoughts on “Putting a Delete Switch in the Record Edit Form

  1. Hello Roland!

    First, excellent plugin. It has been extremely useful to our diaper bank.

    I am trying to allow users to “delete” records from the front end using the first method you describe above. Where I am having issues is the pdb_list shortcode uses a template and filter to show only those signups pertaining to the current user of the site (social service agencies signup as a WordPress user then babies are entered via Participants Database). Once I add the checkbox field and edit the pdb_list shortcode to include the filter=”delete!yes” it breaks the list. I’m all backed up and have tried adding the code before the template call, before and after the existing filter call and even adding “delete!yes” to the existing filter. Do you have any suggestions? Thank you very much!

    Mike

    1. I will also point out that I found your tutorial showing how to string together filters using an & (ampersand) or | (pipe) but neither worked. The page is restricted to only users logged in so I will paste my code below. I will say when I make a change and it doesn’t work then I delete my addition the list is still broken. I have to revert back to my backup before it is fixed.

      [insert_php]
      global $current_user;
      echo(‘

      Welcome ‘ . $current_user->user_login . ‘!

      ‘);
      [/insert_php]

      [insert_php]
      global $current_user;
      echo do_shortcode(‘[pdb_list template="mytemplate" fields="edit_link,child_first_name,child_last_name,parent_first_name,agency_name,agency_rep,last_accessed" filter="user_login='. $current_user->user_login . '"]‘);
      [/insert_php]

      Sorry to be a pain. Thank you very much!

      Mike

      1. One of the things that can happen with shortcodes is they get formatted by the visual editor. Try doing your edits in text mode, then save them before switching back to visual mode. With some themes, they get pretty aggressive about formatting content, and that can break things.

        1. Thank you for the response. I realized that and am now making a little progress. Right now I can get the list to work except it is ONLY showing signups with the delete checkbox selected.

          [insert_php]
          global $current_user;
          echo(‘Welcome ‘ . $current_user->user_login . ‘!’);
          [/insert_php]

          [insert_php]
          global $current_user;
          echo do_shortcode(‘[pdb_list template="mytemplate" fields="edit_link,child_first_name,child_last_name,parent_first_name,agency_name,agency_rep,last_accessed" filter="user_login='. $current_user->user_login . '&delete!yes"]‘);
          [/insert_php]

          The weird thing is =yes shows the result with the delete checkbox marked and !yes shows the same result. I considered changing “delete” to “active” but then I would have to include the active checkbox on all other current records (which is 1000s at this point). Any other advice? I think I’m so close!!!

        2. When setting up these filters, it’s sometimes helpful to know exactly what is in the database for your records. Looking at the database directly using phpMyAdmin or something similar can help you understand what you need to do to filter the list. For instance, if some of them have no value for the delete column, they will show up as “not yes” so you can add a filter for that too:

          delete!yes&delete!

          Or if all the ones you want to show have “no” you can set the filter to only show the ones with a “no” value.

        3. Hey Roland,

          Thank you again for your advice. I finally got this working after a lot of trial and error. What worked for me was to sort the list by showing what does not equal yes which includes any no’s and/or empty values (from before this field was available). The code is below in case it can help someone else in the future. Thank you again Roland!

          [insert_php]
          global $current_user;
          echo(‘Welcome ‘ . $current_user->user_login . ‘!’);
          [/insert_php]

          [insert_php]
          global $current_user;
          echo do_shortcode(‘[pdb_list template="mytemplate" fields="edit_link,child_first_name,child_last_name,parent_first_name,agency_name,agency_rep,last_accessed" filter="user_login='. $current_user->user_login . '&delete!=yes"]‘);
          [/insert_php]

  2. this is not working for me

    1. Hi Holden,

      So, what exactly is not working?

      1. I followed the instruction but it cannot delete a value.

        Thanks

        1. OK, I don’t know where you went wrong, so all I can suggest is to go over the instructions and look for something that you did differently from the tutorial.

Leave a Reply
You have to agree to the comment policy.

10 thoughts on “Putting a Delete Switch in the Record Edit Form

  1. Hello Roland!

    First, excellent plugin. It has been extremely useful to our diaper bank.

    I am trying to allow users to “delete” records from the front end using the first method you describe above. Where I am having issues is the pdb_list shortcode uses a template and filter to show only those signups pertaining to the current user of the site (social service agencies signup as a WordPress user then babies are entered via Participants Database). Once I add the checkbox field and edit the pdb_list shortcode to include the filter=”delete!yes” it breaks the list. I’m all backed up and have tried adding the code before the template call, before and after the existing filter call and even adding “delete!yes” to the existing filter. Do you have any suggestions? Thank you very much!

    Mike

    1. I will also point out that I found your tutorial showing how to string together filters using an & (ampersand) or | (pipe) but neither worked. The page is restricted to only users logged in so I will paste my code below. I will say when I make a change and it doesn’t work then I delete my addition the list is still broken. I have to revert back to my backup before it is fixed.

      [insert_php]
      global $current_user;
      echo(‘

      Welcome ‘ . $current_user->user_login . ‘!

      ‘);
      [/insert_php]

      [insert_php]
      global $current_user;
      echo do_shortcode(‘[pdb_list template="mytemplate" fields="edit_link,child_first_name,child_last_name,parent_first_name,agency_name,agency_rep,last_accessed" filter="user_login='. $current_user->user_login . '"]‘);
      [/insert_php]

      Sorry to be a pain. Thank you very much!

      Mike

      1. One of the things that can happen with shortcodes is they get formatted by the visual editor. Try doing your edits in text mode, then save them before switching back to visual mode. With some themes, they get pretty aggressive about formatting content, and that can break things.

        1. Thank you for the response. I realized that and am now making a little progress. Right now I can get the list to work except it is ONLY showing signups with the delete checkbox selected.

          [insert_php]
          global $current_user;
          echo(‘Welcome ‘ . $current_user->user_login . ‘!’);
          [/insert_php]

          [insert_php]
          global $current_user;
          echo do_shortcode(‘[pdb_list template="mytemplate" fields="edit_link,child_first_name,child_last_name,parent_first_name,agency_name,agency_rep,last_accessed" filter="user_login='. $current_user->user_login . '&delete!yes"]‘);
          [/insert_php]

          The weird thing is =yes shows the result with the delete checkbox marked and !yes shows the same result. I considered changing “delete” to “active” but then I would have to include the active checkbox on all other current records (which is 1000s at this point). Any other advice? I think I’m so close!!!

        2. When setting up these filters, it’s sometimes helpful to know exactly what is in the database for your records. Looking at the database directly using phpMyAdmin or something similar can help you understand what you need to do to filter the list. For instance, if some of them have no value for the delete column, they will show up as “not yes” so you can add a filter for that too:

          delete!yes&delete!

          Or if all the ones you want to show have “no” you can set the filter to only show the ones with a “no” value.

        3. Hey Roland,

          Thank you again for your advice. I finally got this working after a lot of trial and error. What worked for me was to sort the list by showing what does not equal yes which includes any no’s and/or empty values (from before this field was available). The code is below in case it can help someone else in the future. Thank you again Roland!

          [insert_php]
          global $current_user;
          echo(‘Welcome ‘ . $current_user->user_login . ‘!’);
          [/insert_php]

          [insert_php]
          global $current_user;
          echo do_shortcode(‘[pdb_list template="mytemplate" fields="edit_link,child_first_name,child_last_name,parent_first_name,agency_name,agency_rep,last_accessed" filter="user_login='. $current_user->user_login . '&delete!=yes"]‘);
          [/insert_php]

  2. this is not working for me

    1. Hi Holden,

      So, what exactly is not working?

      1. I followed the instruction but it cannot delete a value.

        Thanks

        1. OK, I don’t know where you went wrong, so all I can suggest is to go over the instructions and look for something that you did differently from the tutorial.

Leave a Reply
You have to agree to the comment policy.