0

Ok guys and gals, I'm losing my mind here...

I am looking to append the content and a custom field of a post to a div on page. The ID of the content and custom field is defined by a data attribute on a link to be selected by the user.

Issue is the output of the function called by ajax is not being populated - instead the entire html of the current page is being duplicated instead.

This is the html of the selectors and output div on the page...

<p><a class="funnel-direction" data-funnel-id="123" href="#">Option One</a> <a class="funnel-direction" data-funnel-id="456" href="#">Option Two</a></p>

<div id="result"></div> <!-- whole page gets duplicated in here - wtf? -->

This is enqueuing my script for the ajax call

add_action( 'wp_enqueue_scripts', 'add_ajax_scripts' );

function add_ajax_scripts() {

   wp_enqueue_script( 'funnel-ajax', DNA_FU . 'js/funnel-ajax.js', array(), '1.0.0', true ); // working fine

   wp_localize_script( 'funnel-ajax', 'funnel_ajax', array(
    'ajaxurl'   => admin_url( 'admin-ajax.php' ),
    'ajaxnonce' => wp_create_nonce( 'ajax_post_validation' )
  ));

}

This is the function being called by ajax - it is this content I want to populate in <div id="result"></div>.

add_action ( 'wp_ajax_nopriv_dna_add_funnel_part', 'dna_add_funnel_part' );
add_action ( 'wp_ajax_dna_add_funnel_part', 'dna_add_funnel_part' );

function dna_add_funnel_part() {

  $id       = $_POST['postid'];
  $meta     = get_post_meta($id, 'dna_funnel_info', true);

  $content  = apply_filters('the_content', get_post_field('post_content', $id));
  $data     = !empty($meta) ?  '<p>' . $meta . '</p>' : '';
  
  echo $content . $data;

  wp_die();

}

finally, here is my ajax .js

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

  $('a.funnel-direction').on( 'click', function(e) {
  
    e.preventDefault();

    var postid = $(this).attr('data-funnel-id');

    console.log(postid); // working

    $.ajax({
      type: 'POST',
      url: funnel_ajax.ajax_url,
      data: {
        action: 'dna_add_funnel_part',
        postid: postid,
      },
      success: function(data) {

        // console.log(data);

        $('#result').html(data); // This populates the entire html of the current
                                 // page - it should only popualte the output of 
                                 // the dna_add_funnel_part() wordpress function
      },
      fail: {
        // to do ...
      }
    });

    return false; 

  });

});

Have looked over and over this can can't spot anything hope fully y'all can spot it!

Thanks in advance

8
  • What do you mean by "entire html of the current page"? Do you mean everything including the site header, footer, sidebars etc? Or do you mean the entire content of the page as entered in Pages > All Pages > Edit? I notice your AJAX callback is returning the post_content. Is that what you mean? Or is result just supposed to contain the dna_funnel_info meta? Feb 10 '21 at 11:46
  • Hi Jacob - yes, the entire html header, footer, etc (even the <head>) Feb 10 '21 at 11:51
  • Jacob - and yes the content and dna_funnel_info meta. So is the user clicked the button with data-funnel-id="123" then I want to populate with the both the content and metafield of post ID 123 👍🏼 Feb 10 '21 at 11:53
  • This full HTML page, what is it the page of? The current post? The desired post? A 404? Is there a reason you haven't implemented this as a simple the_contentPHP filter server side? What was the reason for using the older admin ajax API instead of making an AJAX request to the posts rest endpoint at /wp-json/wp/v2/posts/idgoeshere?
    – Tom J Nowell
    Feb 10 '21 at 12:21
  • @TomJNowell - yes, the entire html of the current (not desired) post. I’m not sure what you mean by a server-side filter? The reason behind this method is because the content needs to be served depending on a user’s choice as they progress through the page - we could do this over multiple pages but I wanted to do this without the need of a page refresh. The older Ajax API is being used for two reasons 1) I am simply more familiar with it (normally!) 2 This functionality is to be used onto another site for the client - one which has the REST API disabled for security purposes Feb 10 '21 at 14:08
1

First, you made a really, really silly typo:

'ajaxurl'   => admin_url( 'admin-ajax.php' ),
.....
url: funnel_ajax.ajax_url,

ajaxurl != ajax_url. So your Admin AJAX request is not returning a full HTML page. You're not even hitting the AJAX file!

However, this is still completely the wrong way to go about this


I was going to suggest that you instead use the REST API which is much easier and foolproof, and to write a custom endpoint using register_rest_route to give you a pretty URL such as example.com/wp-json/richerimage/v1/dnafunnel, but you don't need to.

In fact, you don't even need an AJAX handler or an endpoint. Just use the one that core gives you.

First, register the post meta so it appears in the REST API responses:

PHP:

$args = array(
    'type' => 'string',
    'description' => 'DNA Funnel Info thing',
    'single' => true,
    'show_in_rest' => true,
);
register_post_meta( 'post', 'dna_funnel_info', $args );

Then retrieve the desired post, e.g. example.com/wp-json/wp/v2/post/123 where 123 is the ID of the post you wanted. The JSON response will contain the content in its fully rendered form, title, taxonomies, etc, including a meta section with all the meta keys you registered.

If your post ID is for a CPT, make sure show_in_rest is set to true when it's registered, and replace /post/ with the relevant endpoint for that CPT

Or better yet, use PHP:

add_filter( 'the_content', function( $content ) {
    // append post 123's content to the end
    return $content . get_the_content( '', '', 123 );
} );
2
  • Thank you Tom - it was the typo!! Agree with REST API route - reason not pursuing this method is function needs to be replicated on a site which has the API disabled due to security Thanks again 👍🏼 Feb 10 '21 at 17:05
  • @richerimage why would anybody disable the REST API for security reasons? My understanding is that this harms not helps the site, and that very few people do this ( as it breaks lots of things ), and it would be more secure than the AJAX endpoint in your question. Additionally, you said this AJAX call is made from a different site, hence why it isn't done in PHP, so it doesn't matter if that site has a REST API or not, because it's talking to a 3rd party. IMO you're well within your rights to say those sites aren't supported
    – Tom J Nowell
    Feb 10 '21 at 18:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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