0

I have a CPT called albums. The CPT have some custom fields, I want those fields to be blank in the post editor, so the person who is editing a post can ad a track to the album from the editor and then the fields go blank again to add more tracks. My solution was to let the user type in three fields: Interpreter of the song, url of the audio file, and name of the song. Once the fields are filled, the user can click a button that triggers an AJAX call that sends the values of the field to a function in functions.php file with the intention of store the values of those fields in a post meta. Almost everything works, but the values of the fields are not storing in the assigned meta key:

I have been trying to achieve this but I don't know why this is not working. Here's my code:

This is the function where the custom fields are:

function topchart_albums_cpt_cf($post){

    var_dump(get_post_meta($post->ID, "track-info", true)); //It prints string(0) ""

    //All fields appear correctly on the editor of the CPT

    //$album_artist = get_post_meta( $post->ID, 'album-artist', true ); Not needed in this case
    echo '<label for="album-artist">';
    _e( 'Intérprete del track', 'topchart' );
    echo '</label> ';
    echo '<input type="text" id="album-artist" name="album-artist"  size="50" /></br>';

    //$add_new_track = get_post_meta( $post->ID, 'add-new-track', true ); Not needed in this case
    echo '<label for="add-new-track">';
    _e( 'Añadir un nuevo track', 'topchart' );
    echo '</label> ';
    echo '<input type="text" id="add-new-track" name="add-new-track"  size="80" />';

    //$track_url = get_post_meta( $post->ID, 'track-url', true ); Not needed in this case
    echo '<label for="track-url">';
    _e( 'Url del archivo', 'topchart' );
    echo '</label> ';
    echo '<input type="url" id="track-url" name="track-url"  size="100" />';

    echo '<button id="add-track">Añadir track</button></br>';

    $erase_track = get_post_meta( $post->ID, 'erase-track', true );
    echo '<label for="erase-track">';
    _e( 'Borrar un track ', 'topchart' );
    echo '</label> ';
    echo '<select id="erase-track" name="erase-track">';
    if(is_array($erase_track)) { 
        foreach($erase_track as $track ) {
    ?>
            <option value="<?php echo $track; ?>"><?php echo $track; ?></option>

    <?php         
        } 
    } else {
        echo 'No se han incluido tracks (todavía) en este album';  
    }
    echo '</select>';
    echo '<button id="borrar-track">Borrar track</button>';

}

This is in a JS file:

jQuery(document).ready(function($){
    $("#add-track").click(function(){
        var track_artist = $("#album-artist").val();
        var track_name = $("#add-new-track").val();
        var track_url = $("#track-url").val();
        if ( track_name  !== "") {
            $.ajax({
                url : track.ajax_url,
                type : 'post',
                data : {
                action: 'save_track_data',
                track_artist : track_artist,
                track_name : track_name, 
                track_url : track_url                
                },
                success: function(response) {
                    alert("ok"); /*Alert triggers when clicking on the button #add-track in the CPT */
                }

            }); 
        } else {
            alert("Tienes que introducir el título del track"); 
        }
    });
});

Functions to process the Ajax call in functions.php

function add_album_cpt_edit_script($hook) {
    global $post;

    if ( $hook == 'post-new.php' || $hook == 'post.php' ) {
        if ( 'topchart_album' === $post->post_type ) {     
            wp_enqueue_script(  'album-edit-script', get_stylesheet_directory_uri().'/js/album-edit-script.js', array('jquery'), '1.0', true );
            wp_localize_script( 'album-edit-script', 'track', array('ajax_url' => admin_url( 'admin-ajax.php' )));
        }
    }
}
add_action( 'admin_enqueue_scripts', 'add_album_cpt_edit_script', 10, 1 );

Simplified function, but even like this it won't work. I tried several ways with update_post_meta() and add_post_meta() but nothing stores the info. I'm missing something but don't know what, maybe some WordPress AJAX API rule or something.

add_action( 'wp_ajax_save_track_data', 'save_track_data' );
function save_track_data() {
   global $post;
   $track_info = array ($_POST['track_name'] => array ( 'artist' => $_POST['track_artist'], 'url' => $_POST['track_url']));
   add_post_meta($post->ID, 'track-info', $track_info);
   wp_die();
}

Hope someone can help me. Sorry if my code is messy, I have been poking around it triyng to make it work.

1 Answer 1

1

I just resolved this. Apparently, when you do AJAX calls to post edit pages in WordPress, or administrator, things work different and you don't get the ID of the post you are editing. I read a lot of similar questions like this, but none of the solutions worked for me, but they gave me hints.

This is what I did to solve this:

The AJAX code in the JS file:

$("#add-track").click(function(){        
        var track_artist = $("#album-artist").val();
        var track_name = $("#add-new-track").val();
        var track_url = $("#track-url").val();        
        if ( track_name  !== "") {
            $.ajax({
                url : track.ajax_url,
                type : 'post',
                data : {
                action: 'save_track_data',
                track_artist : track_artist,
                track_name : track_name, 
                track_url : track_url,
                post_url : window.location.href, //get the complete url of the post editor, wich includes post id
                execute: "add track" //This is not necessary in this code, I'am using it to know when to erase or add a track 
                },
                success: function(response) {

                }

            }); 
        } else {
            alert("Tienes que introducir el título del track");
        }
    });

The code in functions.php

add_action( 'wp_ajax_save_track_data', 'save_track_data' );
function save_track_data() {    
    $post_url = $_POST['post_url']; //The post edit page's url string from AJAX call
    $id_start = strpos($post_url, 'post=') + 5; //Get the position where the id number starts in the url string
    $id_end = strpos($post_url, '&'); //Get the position where the id number of the post ends
    $post_id = substr($post_url, $id_start, ($id_end - $id_start)); //Extract the number from the urs string
    $tracks_info = get_post_meta($post_id, 'tracks-info', true); //Get the array with the tracks information          
    $track_name = $_POST['track_name'];
    $track_artist = $_POST['track_artist'];
    $track_url = $_POST['track_url'];
    $track_partial = array("artist" => $track_artist, "url" => $track_url);    
    if($tracks_info === '') { //If the meta key has no information
        $track_info[$track_name] = $track_partial; // assign the first array element
         add_post_meta($post_id, 'tracks-info', $track_info); //Save the track info in post meta
    } else { //If the post meta have at least one track
         $tracks_info[$track_name] = $track_partial; //assign a new element to the array of tracks
         update_post_meta($post_id, 'tracks-info', $tracks_info); //Update the post meta
    }    
    wp_die();
}

I hope this helps somebody with the same problem.

1
  • 1
    yes. in general you should never rely on global variables being "magically" set unless you are 100% sure that you are in the right context. Commented Sep 5, 2015 at 3:58

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.