Support

Account

Home Forums Backend Issues (wp-admin) Changing query of Post Object field upon changing the field

Solving

Changing query of Post Object field upon changing the field

  • I have a couple of Post Object fields that are present in a Flexible Content field. In other words, the Flexible Content field has a few layouts and each layout contains Post Object fields only.

    I want to create some kind of synchronization between these Post Object fields and make it so that if I select a post in one of the Post Object fields, that post should not be possible to choose again in either of the other Post Object fields. If I remove the post from the Post Object field (making it null), then that post should be possible to select again.

    I guess that the way to go is using the acf/fields/post_object/query filter. But how do I pass in which posts to exclude from the query into this filter? The query should be modified each time I select a post in any of the Post Object fields, so do I have to do this with an AJAX call through JS and then call the acf/fields/post_object/query filter with that?

  • First you would need to add custom JavaScript. The basics are covered here https://www.advancedcustomfields.com/resources/adding-custom-javascript-fields/

    Using the new JS API for ACF you would create a filter using this hook https://www.advancedcustomfields.com/resources/javascript-api/#filters-select2_args. In this filter you would get the values of the other relationship field and add them to the ajax data being sent. You would do this using the field functions https://www.advancedcustomfields.com/resources/javascript-api/#acf.field.

    Finally you would create the acf/fields/post_object/query filter that would use the information to filter the posts using the new data that is sent, more than likely by adding a post__not_in argument.

    Sorry I can’t be more specific or give you example code, but I don’t have more at the moment.

  • Thank you @hube2!

    Okay, bear with me on this one. I’m aware that the way I retrieve the ID and the featured image is very hackish. So I’ll try to use a more ACF way of doing this eventually. But just to demonstrate my current problem. 🙂

    I have (for now) created something in PHP that echoes the ID and the featured image URL for each post that is selected in the Post Object fields into a hidden div in the Post Object title.

    function my_post_object_result($title, $post, $field, $post_id)
    {
        $post_thumbnail_url = get_the_post_thumbnail_url($post->ID);
    
        $hidden_div = $title;
        $hidden_div .= '<div id="' . $post->ID . '" class="featured-image" style="display:none;">' . $post_thumbnail_url . ' </div>';
    
        return $hidden_div;
    }
    
    add_filter('acf/fields/post_object/result', 'my_post_object_result', 10, 4);

    The featured image URL is used for creating a separate div underneath the Post Object input with the help of JS. As they are used for a grid, it’s important for the admin to see the featured image of the post they select. The ID attribute is then used by JS to create an array containing each post ID that is currently selected, and it’s then sent as the data through AJAX.

    This is what I’m doing in JS on page load:

    $(window).on("load", function() {
    
            $(".acf-field-post-object").each(function() {
                var imageURL = $(this).find(".select2-selection").find(".featured-image").text();
                $(this).find(".acf-input").append("<div class='featured-image-container'><div class='inner'><img src='" + imageURL + "' /></div></div>");
                var newPost = $(this).find(".select2-selection").find(".featured-image").attr("id");
                selectedPosts.push(newPost);
            })
    
            var filteredPosts = selectedPosts.filter(function(id){
            	return id != undefined
            })
            var data = {
                'action': 'my_action',
                'selectedPosts': filteredPosts,
            };
    
            $.post(ajax_object.ajax_url, data, function(response) {
                console.log(response);
            });
    
        })

    The response from AJAX is returning a PHP array with all the selected posts, which is what I want. The my_action function that the AJAX is sending the data to looks like this:

    
    add_action('wp_ajax_my_action', 'my_action');
    function my_action()
    {
        $postitems = $_POST['selectedPosts'];
        print_r($postitems);
        function work_post_object_query($args, $field, $post_id)
        {
            $args['post_status'] = array('publish');
            $args['post__not_in'] = $postitems;
    
            return $args;
        }
    
        // filter for every field
        add_filter('acf/fields/post_object/query', 'work_post_object_query', 10, 3);
        exit();
    }
    

    And this is where I’m experiencing trouble. Is this the correct way of using the filter with the AJAX data? I’m suspecting (apart from the hack I used in the beginning) that I’m doing something very wrong here.

  • Hmm. After editing my reply, it somehow got deleted. So please delete this duplicate if it somehow gets back.

    Thank you @hube2!

    Okay, bear with me on this one. I’m aware that the way I retrieve the ID and the featured image is very hackish. So I’ll try to use a more ACF way of doing this eventually. But just to demonstrate my current problem. 🙂

    I have (for now) created something in PHP that echoes the ID and the featured image URL for each post that is selected in the Post Object fields into a hidden div in the Post Object title.

    function my_post_object_result($title, $post, $field, $post_id)
    {
        $post_thumbnail_url = get_the_post_thumbnail_url($post->ID);
    
        $hidden_div = $title;
        $hidden_div .= '<div id="' . $post->ID . '" class="featured-image" style="display:none;">' . $post_thumbnail_url . ' </div>';
    
        return $hidden_div;
    }
    
    add_filter('acf/fields/post_object/result', 'my_post_object_result', 10, 4);

    The featured image URL is used for creating a separate div underneath the Post Object input with the help of JS. As they are used for a grid, it’s important for the admin to see the featured image of the post they select. The ID attribute is then used by JS to create an array containing each post ID that is currently selected, and it’s then sent as the data through AJAX.

    This is what I’m doing in JS on page load:

    $(window).on("load", function() {
    
            $(".acf-field-post-object").each(function() {
                var imageURL = $(this).find(".select2-selection").find(".featured-image").text();
                $(this).find(".acf-input").append("<div class='featured-image-container'><div class='inner'><img src='" + imageURL + "' /></div></div>");
                var newPost = $(this).find(".select2-selection").find(".featured-image").attr("id");
                selectedPosts.push(newPost);
            })
    
            var filteredPosts = selectedPosts.filter(function(id){
            	return id != undefined
            })
            var data = {
                'action': 'my_action',
                'selectedPosts': filteredPosts,
            };
    
            $.post(ajax_object.ajax_url, data, function(response) {
                console.log(response);
            });
    
        })

    The response from AJAX is returning a PHP array with all the selected posts, which is what I want. The my_action function that the AJAX is sending the data to looks like this:

    
    add_action('wp_ajax_my_action', 'my_action');
    function my_action()
    {
        $postitems = $_POST['selectedPosts'];
        print_r($postitems);
        function work_post_object_query($args, $field, $post_id)
        {
            $args['post_status'] = array('publish');
            $args['post__not_in'] = $postitems;
    
            return $args;
        }
    
        // filter for every field
        add_filter('acf/fields/post_object/query', 'work_post_object_query', 10, 3);
        exit();
    }
    

    And this is where I’m experiencing trouble. Is this the correct way of using the filter with the AJAX data? I’m suspecting (apart from the hack I used in the beginning) that I’m doing something very wrong here.

  • I realised that I didn’t explain what the problem I’m experiencing is, and I don’t want to risk that my previous post gets deleted as well if I edit it. So I’ll do an addition here instead.

    The problem is that the query simply is not changed. If I try to change a Post Object, the Post Objects that already has been selected are still available as selections in the Post Object fields.

  • Sorry to nag about this, but is there anyone who have tried something similar and can provide some example code or have the time to look through my code above and see where I’m mistaken? Would be very appreaciated.

  • Sorry I have not gotten back to you on this, been a little busy on a project.

    Where I think you’re going wrong, there are 2 places.

    The first thin is that you need to return JSON from your AJAX function

    
    echo json_encode($postitems);
    

    The second thing is that you can’t add an action during the AJAX request because the action will no longer exist when ACF makes it’s AJAX request.

    What you need to do is alter the ACF AJAX request rather than doing your own to include your extra values and then in your filter use these additional values to alter the query that ACF is doing. Unfortunately, that’s as far as I can take you. While I think that it’s possible to do this, I don’t know exactly how and it would take a lot of digging and time for me to figure it out. There aren’t any examples of doing this that I know of.

Viewing 7 posts - 1 through 7 (of 7 total)

The topic ‘Changing query of Post Object field upon changing the field’ is closed to new replies.