Support

Account

Home Forums ACF PRO How can I disable for selecting "non-public" posts from lists in relation field?

Solved

How can I disable for selecting "non-public" posts from lists in relation field?

  • I am using relationship field to select posts from lists which are divided into two(left / right).

    Then I wanna prevent selecting “non-public” posts from the left-side list column.

    I know I can use ‘acf/fields/relationship/query’ hook to restrict post_status to be shown in the list with code like below.

    function my_post_status_filter($args){
    	$args['post_status'] = array( 'publish' );
    	return $args;
    }
    

    But I want to keep all posts shown in lists,
    and wanna disable for selecting “non-public” posts at once.

    Is there any solution?

  • Hi @hiroshi

    So you’re using a single relationship field to create some sort of left to right relation between all your posts?
    That’s a creative way to use it I must say πŸ™‚

    However I think it’d be hard to do what you ask for. like you’ve noticed if you change the query the non-public posts wont even appear in the field at all.
    I think your best solution would be to instead maybe use two different relationship fields and restrict one of them.

    Or do a bit of ugly custom Javascript hacking to prevent posts that are non-public to be selectable in the relationship field. But I can’t promise it’s possible and I feel that testing this myself is a bit outside normal forum support πŸ™‚

  • Hi @jonathan

    Thank you for your replay!
    The way I described my situation was too bad to be understood, I think… (because of my bad command of English…)

    Anyway, I made it by (you might call) “custom Javascript hacking” + using ACF hook finally.

    The attachment is partly in Japanese. so please bear with it.
    As you see, my relationship field is shown as split 2 column. (I do not know how they call it.)

    First, I used ACF hook ‘acf/fields/relationship/result’ to insert some kind of flag for “cannotselect” item like below.

    add_action('acf/fields/relationship/result', 'add_extra_to_title' ,10 ,4);
    function add_extra_to_title( $title, $post, $field, $post_id ) {
    
    	//prepare Jap translation for post_status
    	$poststatus_jp = array(
    		'draft' => '下書き',
    		'private' => 'ιžε…¬ι–‹',
    		'pending' => 'レビγƒ₯ー待け',
    		'future' => 'δΊˆη΄„ζŠ•η¨Ώ',
    	);
    
    	$post_status = get_post_status( $post->ID );
    
    	//add flag for "cannotselect" item
    	if( $post_status != "publish" )
    	{
    		$title .= '<span class="cannotselect"> *<span>';
    	}
    
    	//replace Eng to Jap.
    	if( $post_status != "publish" )
    	{
    		if(isset( $poststatus_jp[ $post_status ] ) ){
    			$post_status_jp = $poststatus_jp[ $post_status ];
    		}
    		$title = str_replace( "($post_status)" , "($post_status_jp)" ,  $title );
    	}
    
    	//if it's post, add category name to it's title.
    	$thisPost = get_post( $post->ID );
    	$thisPosttype = $thisPost->post_type;
    	$thisTerms = wp_get_post_terms( $post->ID, 'category' );
    	if( $thisPosttype == 'post' && !empty($thisTerms) )
    	{
    		$title .= "&nbsp;&nbsp;[" . $thisTerms[0]->name . "]";
    	}
    
    	return $title;
    }
    

    Next, using setTimeout + jQuery, add “cannotselect” class to li element which include span.cannotselect.
    Plus, apply “pointer-events : none;” + pale pink background to li.cannotselect to be noticeable.

    javascript part

            function watchAcfRelItem()
            {
    			if( $( ".acf-rel-item" ).length > 1 ){
    				$('.acf-rel-item span.cannotselect').each( function(){	
    					$(this).parent().parent().addClass('cannotselect');
    				});
    			}
    			setTimeout( watchAcfRelItem, 1000 );
            }
            watchAcfRelItem();
    

    css part

    	li.cannotselect .acf-rel-item {
    		background: pink;
    		pointer-events : none;
    		cursor: not-allowed;
    		opacity: 0.5;
    	}
    	li span.cannotselect{
    		display: none;
    	}
    

    As you see, it’s ungly… but seems working so far.

    If you have any better idea, please tell it to me.
    I will appreciate your kindness greatly!

    Thank you again for reading my bad English!

  • Hi @hiroshi

    No worries! English is not my native language either and I think you’re quite good compared to many other I talk to.

    Yes that was pretty much what I had in mind as well. I might’ve tweaked it a little bit.

    However it doesn’t seem like you actually prevent these from being selected? The user can still select the “cannotselect” posts correct?

  • I tweaked your code a bit so it now also definitely prevents the user from even being able to select the post.

    PHP:

    
    add_action('acf/fields/relationship/result', 'add_extra_to_title' ,10 ,4);
    function add_extra_to_title( $title, $post, $field, $post_id ) {
    
    	//prepare Jap translation for post_status
    	$poststatus_jp = array(
    		'draft' => '下書き',
    		'private' => 'ιžε…¬ι–‹',
    		'pending' => 'レビγƒ₯ー待け',
    		'future' => 'δΊˆη΄„ζŠ•η¨Ώ',
    	);
    
    	$post_status = get_post_status( $post->ID );
    
    	//add flag for "cannotselect" item
    	if( $post_status != "publish" )
    	{
    		$title = '<span class="cannotselect">' . $title . '</span>';
    	}
    
    	//replace Eng to Jap.
    	if( $post_status != "publish" )
    	{
    		if(isset( $poststatus_jp[ $post_status ] ) ){
    			$post_status_jp = $poststatus_jp[ $post_status ];
    		}
    		$title = str_replace( "($post_status)" , "($post_status_jp)" ,  $title );
    	}
    
    	//if it's post, add category name to it's title.
    	$thisPost = get_post( $post->ID );
    	$thisPosttype = $thisPost->post_type;
    	$thisTerms = wp_get_post_terms( $post->ID, 'category' );
    	if( $thisPosttype == 'post' && !empty($thisTerms) )
    	{
    		$title .= "&nbsp;&nbsp;[" . $thisTerms[0]->name . "]";
    	}
    
    	return $title;
    }
    
    function my_acf_admin_enqueue_scripts()
    {
           wp_enqueue_script('customstuff', get_template_directory_uri() . '/customscript.js');
    }
    
    add_action('acf/input/admin_enqueue_scripts', 'my_acf_admin_enqueue_scripts');
    

    JS:

    
    jQuery(document).ready(function(){
    
    	watchAcfRelItem();
    	jQuery('.acf-bl').on('click', '.cannotselect', function(e){
    
    		e.preventDefault();
    		return false;
    
    	});
    
    });
    
    function watchAcfRelItem(){
    
    	jQuery('span.cannotselect').each(function(index, key){
    		jQuery(this).closest('li').addClass('cannotselect');
    
    	});
    
    	setTimeout( watchAcfRelItem, 1000 );
    
    }
    
    

    You can keep your CSS as it is πŸ™‚

  • Hi @jonathan

    Thanks again!

    Yes! the way you suggested is much smarter and less code than mine!

    Mine worked because of css “pointer-events : none;” applied for li.cannotselect.
    But “pointer-events” works only newer browsers.
    So “e.preventDefault()” is definitely better.

    Actually, I tried these below at first and failed…
    Then I gave up using “e.preventDefault()” for this case.

    
    		$('li.cannotselect').on('click', function(e){
    			e.preventDefault();
    			return false;
    		});
    

    Also, I wanted to know if it’s possible to sort this out without using “setTimeout()”,
    but you use “setTimeout()” too.
    So I felt relieved in a sense πŸ˜‰

    Anyway, thank you a lot!
    Much love from me and heaven above!

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

The topic ‘How can I disable for selecting "non-public" posts from lists in relation field?’ is closed to new replies.