2

I have a loop of posts and I allow a user to edit each post using ajax. When the edit button is clicked for the post I use ajax to retrieve the template part containing the edit form for the post. Easy enough to do by creating a function with 'get_template_part' and then localizing a script where I use $ajax to execute the function.

Now here is my problem. I need to process the form with ajax that is in the template part we've called. In order to do anything with jquery for that form, the jquery has to be added as an inline script to the template. So when the button is clicked inside the from to save and edits made, I then need to run my php function that processes any edits made. But I can't do that because I can't actually localize the inline script that will allow me to use that php function I've made. Any ideas.

UPDATE:

Ok so instead of adding the scripts to the template inline, I register the script inside the function that gets the template part and then print it which I thought would give me a chance to localize. The script works for the template part but it isn't localized.

 add_action('wp_ajax_fetch_dashboard_edit_form', 'fetch_dashboard_edit_form'); 
 function fetch_dashboard_edit_form() {
    $post_id = $_POST['postId'];
    $edit_type = $_POST['editType'];
    include(locate_template('edit-'.$edit_type.'.php'));    
    wp_register_script(
     'fod_edit_script',
     get_bloginfo('stylesheet_directory') . '/libs/edit.js',
     array( 'jquery' ),
     null,
     true
    );
    wp_localize_script(
     'fod_edit_script',
     'editAjax',
     array(
        'ajaxurl' => admin_url( 'admin-ajax.php' )
     )
    );
    wp_print_scripts("fod_edit_script");
 }
2
  • Are you trying to get a post ID or something with the script localization? Nov 28, 2012 at 22:11
  • Im trying to use a php function. Nov 28, 2012 at 23:21

1 Answer 1

2

Sidestep the entire issue and just include fo_edit_script in the header of the page, rather than in the AJAX part. There's no need at all to do this.

You might think that by only including it when its needed your optimising but your not, because it's having to load it every time you open an edit form.

I'd go as far to say that what you're trying to do is bad practice. Avoid pulling in html via AJAX containing references to remote JS files or script tags at every opportunity.

So the simple answer to how to do this is: don't.

You have:

Foreach post
    On AJAX
        include HTML
        Setup JS

Instead:

Setup JS
foreach post
    On ajax
        include HTML

As a metaphor:

A car salesman has 5 customers arrive at his dealership. They each ask for a Honda Civic. What your doing is the equivalent, of the Honda Salesman building 5 factories to produce a single car for each customer.

What you have, is a problem building new factories quickly. Instead of figuring out the solution to the instant new factory problem, build 1 single factory at the start when the car is designed, and use it to produce all the cars.

So only return the needed html in your AJAX call:

add_action('wp_ajax_fetch_dashboard_edit_form', 'fetch_dashboard_edit_form'); 
function fetch_dashboard_edit_form() {
    $post_id = $_POST['postId'];
    $edit_type = $_POST['editType'];
    include(locate_template('edit-'.$edit_type.'.php'));
}

Enqueue your script on the screen showing the posts:

function add_fod_script(){
    wp_register_script(
     'fod_edit_script',
         get_bloginfo('stylesheet_directory') . '/libs/edit.js',
         array( 'jquery' ),
         null,
         true
    );
    wp_enqueue_script('fod_edit_script');
}
add_action('admin_init','add_fod_script');

And adjust edit.js accordingly.

This also has the bonus that when you first edit a post, you dont have a delay when the browser is grabbing edit.js, because it has already been loaded.

It also means you've only included your JS once, so you don't litter your DOM with the same script tag over and over again

You should keep in mind that once the AJAX html is setup and inserted into the DOM, the new elements will not have the event triggers that you setup on DOM ready attached, they will need to be re-added, either more calls, or by orignally using things such as the 'on'jquery functionality:

http://api.jquery.com/on/

e.g. instead of saying:

$("#dataTable tbody tr").click( function(event){
    alert($(this).text());
});

Which means for any dataTabletbody tr that we can find at this moment in time, add an event click handler, do this instead:

$(document).on("click", "#dataTable tbody tr", function(event){
    alert($(this).text());
});

Which means the same thing but for any datatable tbody tr that currently or will ever exist in the future.

So we can elaborate on what we had earlier:

Include JS
Setup JS for page
foreach post
    On ajax
        include AJAX HTML
        Setup JS events again, for the AJAX HTML

Should you really, really, really want to continue doing it the way you're doing it, there is a solution, but as I have said, what you're doing is bad, bad practice, and will only lead to more difficulties, duplication, and problems. It's putting band aids on band aids. Refer to this:

https://stackoverflow.com/questions/235967/calling-a-jquery-function-inside-html-return-from-an-ajax-call

5
  • The problem is the JS wont work for anything inside the template part added with ajax. That's the whole reason for loading the script everytime I load a template. I have to include the JS inline or print it. Nov 28, 2012 at 20:14
  • that's what your question should have been, you need to add your event triggers etc to the elements you've just acquired via AJAX
    – Tom J Nowell
    Nov 28, 2012 at 21:34
  • 1
    I've updated my question. I strongly recommend against including javascript in your templates, you're not fixing a problem you're just introducing yourself to a whole new set of problems ( e.g. going to WPSE to get a fix for your fix is a major warning sign )
    – Tom J Nowell
    Nov 28, 2012 at 21:46
  • I was using .on() from the start but it wasn't working with a loaded script because I was using the bind instead of the delegate version. stackoverflow.com/questions/9698936/… So to make it work with dynamic content it needs to be $(document).on(event, selector, function() {. Nov 29, 2012 at 2:29
  • Ah yes bind is ancient, it was deprecated in favour of live, which has now been deprecated in favour of on, I'd have thought they'd have removed bind in the newer jquery releases
    – Tom J Nowell
    Nov 29, 2012 at 9:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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