Support

Account

Forum Replies Created

  • If there’s a better way to do this, let me know. This is how I was able to do it:

    ( function( $ ) {
    
    	if( 'object' !== typeof acf ) {
    		return;
    	}
    	
    	/**
    	 * Override Gallery Field onClickRemove method.
    	 * This method removes the attachment from the galllery but not the server.
    	 * Runs on media [x] click and "Remove" in gallery sidebar.
    	 *
    	 * @param e Event
    	 * @param $el DOMObject
    	 *
    	 * @return void
    	 */
    	acf.models.GalleryField.prototype.onClickRemove = function( e, $el ) {
    		
    		e.preventDefault();
    		e.stopPropagation();
    
    		let attachment_id = $el.data( 'id' );
    
    		if( attachment_id ) {
    			attachment_id.removeAttachment( attachment_id );
    		}
    		
    		/* AJAX to delete the physical attachment. */
    		
    	};
    
    } )( jQuery );
  • I think one issue might be that there are multiple forms on the same page. What I ended up doing was simply setting the values manually whenever the modal opens:

    acf.set( 'post_id', formContent.find( '#_acf_post_id' ) );
    acf.set( 'screen', 'acf_form' );
    acf.set( 'validate', true );
  • Maybe try:

    acf.validation.addError( {
    input: ‘insert_input_name_here’,
    message: ‘insert message here’
    } );

  • Using the wp_enqueue_scripts hook, loaded into the footer. I’ve also tried to call the above snippet on its own in a wp_footer hook but still doesn’t seem to console out anything either on page load or when opening the Media Library to add-in files.

  • Thanks for the suggestion, but I can’t seem to get this to fire at all. It’s not inside a repeater, it’s just a basic, flat frontend form. Here’s the code I was using:

     if( 'object' == typeof acf ) {
    	acf.addAction( 'append', function( $el ) {
    		console.log( $el );
    	} );
    }
  • I know this is an old thread but I was looking to do something similar. I’ve found the easiest solution to trigger acf validation early is the following:

    let valid = acf.validateForm( {
    	form: $( '#acf-form' ),
    } );
  • Anddddddd as it turns out I forgot that I had ACF already installed and active before integrating it into my custom plugin. The two were conflicting. Once I uninstalled active plugin the issue was solved.

  • Oh no, I’m sorry, you’re right. The acf_get_field_groups() with no parameters does return all the fields but it doesn’t seem ( or at least in my case ) check against location rules. It’s only when I pass in filterable parameters ( like post_type above ) does it call acf_filter_field_groups() and match against location rules.

  • Thanks!

    What I’ve found is: passing parameters to acf_get_field_groups() will run any group location rules. Passing no (or empty) parameters will not check all groups but instead returns nothing. So, I was able to use the following to run my custom location match() method:

    $field_groups = acf_get_field_groups( array(
    	'post_type' => get_post_type(),
    ) );
  • I’m not sure the above works anymore. I keep running into empty posts created and can only be deleted from the database.

    The ACF method pre_save_post expects something numeric OR ‘new_post’ so what I do is pass neither of those things but instead 'post_id' => 'no_new_post' which seems to work. I also use acf/save_post hook at a priority less than 10 ( in my case 4 ).

    I also get errors when unsetting $_POST['acf'] so I’ve been opting to use $_POST['acf'] = array();

    Undefined index: acf in advanced-custom-fields-pro\includes\acf-form-functions.php on line 157

  • Yeah this is something I would also like to see. Maybe an option for select ( kind of like selecting an icon ).

  • You’re right that there wouldn’t be a way to prevent the post from being submitted but there is a way to prevent the post being saved which in my use-case works just as well.

    The acf/save_post hook with a priority less than 10 will fire before the post is saved. At this point I hit my API and if it fails I use the following code to redirect.

    global $wp;
    
    if( $apifailed ) {
    	
    	$_POST['acf'] = array();
    	$query_args = $_GET;
    	$query_args['updated'] = 'notupdated';
    	$query_args['errcode'] = 1;
    
    	wp_safe_redirect( add_query_arg( $query_args, home_url( $wp->request ) ) );
    	exit();
    	
    }

    ACF expected the updated query var parameter to not be empty ( it assumes 1 ) so to be clear that a post was not updated and that the updated parameter exists but is not empty I put a string message to indicate this.

    Finally, the ACF form runs validate right off the bat, always. At this point I can modify the args to handle the error code:

    /**
     * Modify the ACF Form args
     *
     * @param Array $args
     *
     * @return Array $args
     */
    function prefix_modify_form_args( $args ) {
    	
    	if( isset( $_GET['errcode'] ) ) {
    		
    		/**
    		 * Can switch the errcode but we'll go with something generic
    		 */
    		$args['updated_message'] = esc_html__( 'Something went wrong, XYZ not updated.' );
    		$args['html_updated_message'] = str_replace( 'class="updated"', 'class="error"', $args['html_updated_message'] );
    		
    	}
    	
    	return $args;
    	
    }
    add_filter( 'acf/validate_form', 'prefix_modify_form_args' );
  • Thank you for your suggestion and pointing out how the Select2 handles search. I had just assumed Select2 was doing a text based search via JavaScript on the results. Knowing this, I went ahead an used the same code WooCommerce uses to search their shop_orders. The whole function is below:

    /**
     * WooCommerce Shop Order titles are not search friendly.
     * Use the same thing WooCommerce does to modify search.
     * 
     * Taken straight from WooCommerce
     * woocommerce/includes/admin/list-tables/class-admin-list-table-orders.php
     * LN 870
     * FN search_custom_fields()
     *
     * @param WP_Query $wp
     * 
     * @return void
     */
    function prefix_modify_shop_order_search_select( $wp ) {
    	
    	if( ! ( isset( $_REQUEST['action'] ) && 'acf/fields/post_object/query' == $_REQUEST['action'] ) ) {		// Ensure we are in an ACF post_object query action
    		return;
    	} else if( ! ( isset( $_REQUEST['post_id'] ) && 'options' == $_REQUEST['post_id'] ) ) {					// Ensure we're in an option page ( Specific to my usecase )
    		return;
    	} else if( ! ( 'shop_order' == $wp->query_vars['post_type'] && ! empty( $wp->query_vars['s'] ) ) ) {	// Ensure that the query is a shop_order query and search is not empty.
    		return;
    	}
    	
    	/**
    	 * All the below is WooCommerce Specific
    	 */
    	$post_ids = wc_order_search( wc_clean( wp_unslash( $wp->query_vars['s'] ) ) ); // WPCS: input var ok, sanitization ok.
    
    	if ( ! empty( $post_ids ) ) {
    		// Remove "s" - we don't want to search order name.
    		unset( $wp->query_vars['s'] );
    
    		// so we know we're doing this.
    		$wp->query_vars['shop_order_search'] = true;
    
    		// Search by found posts.
    		$wp->query_vars['post__in'] = array_merge( $post_ids, array( 0 ) );
    	}
    	
    }
    add_action( 'parse_query', 'prefix_modify_shop_order_search_select' );

    WooCommerce already has the query_vars in place and ready to be parsed. At this point WooCommerce does the heavy lifting. Valid as of WooCommerce version 3.8.0

  • So the validation is run on admin-ajax.php which invalidate the $pagenow. Maybe there’s a better way to do this but I just made 2 arrays to check against both the global and the referrer.

    Open to way to make the below and above better

    /**
     * Ensure our particular fields pass validation
     * 
     * @param Boolean $valid
     * 
     * @return Boolean $valid
     */
    function theme_acf_nonrequired_fields_validate( $valid ) {
    	
    	global $pagenow;
    	
    	$acceptable_pagenows = array( 'user-new.php', 'user-edit.php', 'profile.php' );
    	$acceptable_referers = array( '/wp-admin/user-new.php', '/wp-admin/user-edit.php', '/wp-admin/profile.php' );
    	
    	if( ! is_admin() || ! current_user_can( 'edit_posts' ) ) {
    		return $valid;
    	}
    	
    	if( ! ( in_array( $pagenow, $acceptable_pagenows ) ||
    		  ( isset( $_REQUEST, $_REQUEST['_wp_http_referer'] ) && in_array( $_REQUEST['_wp_http_referer'], $acceptable_referers ) ) )
    	) {
    		return $valid;
    	}
    	
    	return true;
    	
    }
    add_filter( 'acf/validate_value/name=cust_name', 		'theme_acf_nonrequired_fields_validate' );
  • This happens when I’m using the Post Object dynamic select. The solution ended up being found in a topic from 16′

    https://support.advancedcustomfields.com/forums/topic/using-acf_form-in-admin/#post-38999

    add_action('admin_enqueue_scripts', function() {
    	
    	global $pagenow;
    	
    	if ( 'index.php' != $pagenow ) {
    		return;
    	}
    	
    	wp_enqueue_script('acf-input');
    	
    } );

    Maybe a topic on this would be helpful to others in the future trying to do a similar feature.

  • What plugins are you using to make the icons appear? That’s probably what is adding the commas, not ACF specifically.

  • Are the fields added on the page or on the nav menu item itself ( Via Appearance -> Menus )?

    Have you tried get_field( $item->ID )?

    Additionally, the walker method should look like this:

    function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {

    Your current method is missing $item entirely. It may be helpful to turn on PHP Debugging.

    https://developer.wordpress.org/reference/classes/walker_nav_menu/

  • @mcnab It looks like this:

    /**
     * Load value from custom table
     * 
     * @param Mixed $value
     * @param Integer $post_id
     * @param Array $field
     * 
     * @return $value
     */
    function populate_custom_table_data( $value, $post_id, $field ) {
    
    	if( ! empty( $value ) ) {
    		return $value;
    	}
    
    	$has_parent_field	= false;
    	$field_name 		= $field['name'];
    
    	/**
    	 * Grab parent field and get value by the parent field name
    	 * Use conditional below to populate the actual fields.
    	 */
    	if( ! empty( $field['parent'] ) && false !== strpos( $field['parent'], 'field_' ) ) {
    
    		// false, false is important to prevent infinite recursive loop.
    		$parent_field 	  = get_field_object( $field['parent'], $post_id, false, false );
    		$has_parent_field = ( ! empty( $parent_field ) );
    		$field_name 	  = ( $has_parent_field ) ? $parent_field['name'] : $field_name;
    
    	}
    	
    	// Grab data from custom table
    	$db_data   	= $this->data_util->get_data( $post_id, $field_name );
    	$value		= $db_data;
    
    	// Return early if value is empty
    	if( empty( $value ) ) {
    		return $value;
    	}
    
    	// We're in a subfield
    	if( $has_parent_field ) {
    
    		$field_concat_name = $field['name'];
    		$field_concat_name = str_replace( sprintf( '%1$s_', $field_name ), '', $field_concat_name );
    		preg_match( '(\d{1,})', $field_concat_name, $possible_keys );
    
    		if( ! empty( $possible_keys ) ) {
    
    			$arr_index 			= $possible_keys[0];
    			$field_concat_name 	= str_replace( sprintf( '%1$d_', $arr_index ), '', $field_concat_name );
    
    			// Now we know what index in our subarray
    			$subfield_arr		= $db_data[ $arr_index ];
    
    			// Overwrite $value to actual subfield value
    			// Now that we know the name we can grab it from our named index array
    			$value = ( ! empty( $subfield_arr[ $field_concat_name ] ) ) ? $subfield_arr[ $field_concat_name ] : '';
    		}
    		
    
    	} else if( 'repeater' == $field['type'] ) {	// Return repeater count
    
    		$value = count( $db_data );
    
    	}
    
    	return $value;
    
    }
    add_filter( 'acf/load_value', 'populate_custom_table_data', 20, 3 );
  • On Advanced Custom Fields Free there doesn’t seem to be an out of the box way to do so. There’s a plugin which claims to do so for ACF 5 ( pro ):

    https://wordpress.org/plugins/acf-get-nav-menus/

    But whenever installed using ACF 4 ( free ) it doesn’t seem to work and may break on install. The description says it only support ACF 5+ ( which I haven’t tested on ).

    – – –

    That being said you could achieve this using the hooks that ACF provides developers to work with, is this an option? You would need to add the code into a function.php file or as a separate plugin.

  • It would, just use the same method as the first with 4 conditionals

    $price1 = get_field( 'foo' );
    $link1 = get_field( 'bar' );
    if( $price1 && $link1 ) {
    	$return .= '<a href="' . esc_url( $link1 ) . '">' . $price1 . '</a>';
    }

    If none of the conditionals run, $return will be empty and you can check against that to return you default string.

  • It doesn’t seem like the redirect value is cached. Looking at the code you can see that it simply uses wp_redirect() with a default status of 302:

    /wp-content/plugins/advanced-custom-fields-pro/includes/forms/form-front.php
    acf_form_front::submit_form() LN 451
    
    // redirect
    if( $return ) {
    	
    	// update %placeholders%
    	$return = str_replace('%post_id%', $post_id, $return);
    	$return = str_replace('%post_url%', get_permalink($post_id), $return);
    	
    	
    	// redirect
    	wp_redirect( $return );
    	exit;
    	
    }

    Whatever is caching the redirect it doesn’t seem like it would be Advanced Custom Fields. Could it be another plugin or theme function interfering?

  • If you’re variables are named like above you could loop through them with a for() loop and take advantage of the $i incrementor:

    function displayprice() {
    
    	$return		= '';
    	
    	for( $i = 1; $i <= 3; $i++ ) {
    		
    		$price = get_field( "price{$i}" );	// price1, price2, price3
    		$link  = get_field( "link{$i}" );	// link1, link2, link3
    		$return .= sprintf(
    			'<a href="%1$s" class="%2$s">%3$s</a>',
    			esc_url( $link ),
    			"price{$i}",
    			$price
    		);
    		
    	}
    	
    	if( empty( $return ) ) {
    		$return = __( 'Not Available' );
    	}
    
    	return $return;
    	
    }
    add_shortcode( 'showprices', 'displayprice' );
  • I found a possibly unstable solution but it seems to work so far without any kind of notices or errors ( as of yet ). It takes advantage of both the relationship query hook to set a specific flag and the posts_clauses hook to join the postmeta table and search on that. The SQL solution was found via Iconic WP blog post of a similar nature.

    /**
     * Product relationship field - include searching SKU
     * 
     * @param Array $args
     * @param Array $field
     * @param Integer $post_id
     * 
     * @return $args 
     */
    function prefix_product_relationship_query_mods( $args, $field, $post_id ) {
    
    	$args['post_status'] = 'publish';
    
    	if( ! empty( $args['s'] ) ) {
    		$args['acf_sku_search'] = true;
    	}
    
    	return $args;
    
    }
    add_filter( 'acf/fields/relationship/query/name=field_name', 'prefix_product_relationship_query_mods', 10, 3 );
    
    /**
     * Modify the query clauses to search on the postmeta table when asked to :)
     *
     * @param Array $clauses
     * @param WP_Query $query
     *
     * @return Array $clauses
     */
    function prefix_acf_relationship_search_sku( $clauses, $query ) {
    
    	global $wpdb;
    
    	if( $query->get( 'acf_sku_search', false ) ) {
    
    		$clauses['join'] 	= " LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id ";
    		$clauses['where'] 	= preg_replace(
    			"/\(\s*{$wpdb->posts}.post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
    			"({$wpdb->posts}.post_title LIKE $1) OR ({$wpdb->postmeta}.meta_key = '_sku' AND {$wpdb->postmeta}.meta_value LIKE $1)",
    			$clauses['where']
    		);
    		$query->set( 'acf_sku_search', false );	// Set to false just in case.
    
    	}
    
    	return $clauses;
    
    }
    add_filter( 'posts_clauses', 'prefix_acf_relationship_search_sku', 10, 2 );
  • WooCommerce has _a literal ton_ of hooks to use. If you open up the plugin folder ( plugins/woocommerce/templates ) you can open up those files and see just how many you can hook into.

    The one you’re looking for is in the content-single-product.php file:

    /**
     * Display value after single product titles
     *
     * @return void
     */
    function prefix_after_title() {
    	echo get_field( 'after_title' );
    }
    add_action( 'woocommerce_single_product_summary', 'prefix_after_title', 6 );

    We need the priority of 6 because the file linked above shows that the title is prioritized at 5. If we wanted to display this before the title we would need to change the priority to something before 5.

  • The first thing I would do is check the global $post ID to make sure that’s what you expect it to be. You can error_log( print_r( $post, 1 ) ); if you have error logging turned on. That would be the only thing I can thing of that would be messing up actually getting the field content.

Viewing 25 posts - 1 through 25 (of 62 total)