Support

Account

Home Forums Search Search Results for 'event date repeater'

Search Results for 'event date repeater'

reply

  • Yes, getting a value and then using that value to update another post with the same data will fail, I don’t even need to test it. The reason is that when you use get_field(), even if you use the field key, the nested sub fields in it will be by field name and not field key, so it fails.

    In your code example:

    
    $date_meta = array();
    $date_meta['field_5b21449202e42'] = 'date'; //event_date_type
    $date_meta['field_5b2145b902e43'][0] = array( //event_single_day
    
    // this is the field your are updating in the
    // update field call below
            'field_5b21463202e44' => $date, //event_date 
    
            'field_5b2146c83d961' => array( //event_time
                0 => array(
                    'field_5b2147733d964' => $time, //event_start_time
                    'field_5b2147af3d965' => $time, //event_end_time
                    )
                )
            );
    update_field( 'field_5b21463202e44', $date_meta, $id ); //event_date
    

    field_5b21463202e44 looks like a nested repeater, see my notes above. Is this correct?

  • Hi,

    I’m having an issue with displaying multiple google maps that are not in an accordion.

    I created a repeater for different locations, for each row I have the name of the location and the google map field. I tried to output that in my template using the code provided by ACF, but the maps appear with no pin/marker, and are not in the right spot on the map.

    If I have only one row in my repeater, it works fine. So I’m assuming that it’s a problem between the js and my html elements.

    Each map div has the class .acf-map, but I see in the js that it uses .each to make sure it works for multiple maps.

    Is there something wrong with my code? (note that I don’t want multiple markers in one map, but multiple maps with each one marker).

    <?php if(have_rows('contact_locations_repeater')): ?>
    				<?php while(have_rows('contact_locations_repeater')): the_row(); ?>
    					<div class="location">
    						<div class="map">
    							<!-- GOOGLE MAP-->
    							<?php 
    							$location = get_sub_field('google_map');
    							if( !empty($location) ):
    							?>
    							<div class="acf-map">
    								<div class="marker" data-lat="<?php echo $location['lat']; ?>" data-lng="<?php echo $location['lng']; ?>"></div>
    							</div>
    
    							<?php endif; ?>
    							<!-- END GOOGLE MAP-->  
    						</div>
    						
    							<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDsVBtPm96bvZOTLPy6yBxGBxHE9TU8mtw"></script>
    							<script type="text/javascript">
    							(function($) {
    
    							/*
    							*  new_map
    							*
    							*  This function will render a Google Map onto the selected jQuery element
    							*
    							*  @type	function
    							*  @date	8/11/2013
    							*  @since	4.3.0
    							*
    							*  @param	$el (jQuery element)
    							*  @return	n/a
    							*/
    
    							function new_map( $el ) {
    
    								// var
    								var $markers = $el.find('.marker');
    
    								// vars
    								var args = {
    									zoom		: 18,
    									center		: new google.maps.LatLng(0, 0),
    									mapTypeId	: google.maps.MapTypeId.ROADMAP
    								};
    
    								// create map	        	
    								var map = new google.maps.Map( $el[0], args);
    
    								// add a markers reference
    								map.markers = [];
    
    								// add markers
    								$markers.each(function(){
    
    									add_marker( $(this), map );
    
    								});
    
    								// center map
    								center_map( map );
    
    								// return
    								return map;
    
    							}
    
    							/*
    							*  add_marker
    							*
    							*  This function will add a marker to the selected Google Map
    							*
    							*  @type	function
    							*  @date	8/11/2013
    							*  @since	4.3.0
    							*
    							*  @param	$marker (jQuery element)
    							*  @param	map (Google Map object)
    							*  @return	n/a
    							*/
    
    							function add_marker( $marker, map ) {
    
    								// var
    								var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng') );
    
    								// create marker
    								var marker = new google.maps.Marker({
    									position	: latlng,
    									map			: map,
    									title:    'DSRU',
    									icon:     '<?php the_field('map_pin');?>' 
    								});
    
    								// add to array
    								map.markers.push( marker );
    
    								// if marker contains HTML, add it to an infoWindow
    								if( $marker.html() )
    								{
    									// create info window
    									var infowindow = new google.maps.InfoWindow({
    										content		: $marker.html()
    									});
    
    									// show info window when marker is clicked
    									google.maps.event.addListener(marker, 'click', function() {
    
    										infowindow.open( map, marker );
    
    									});
    								}
    
    							} 
    
    							/*
    							*  center_map
    							*
    							*  This function will center the map, showing all markers attached to this map
    							*
    							*  @type	function
    							*  @date	8/11/2013
    							*  @since	4.3.0
    							*
    							*  @param	map (Google Map object)
    							*  @return	n/a
    							*/
    
    							function center_map( map ) {
    
    								// vars
    								var bounds = new google.maps.LatLngBounds();
    
    								// loop through all markers and create bounds
    								$.each( map.markers, function( i, marker ){
    
    									var latlng = new google.maps.LatLng( marker.position.lat(), marker.position.lng() );
    
    									bounds.extend( latlng );
    
    								});
    
    								// only 1 marker?
    								if( map.markers.length == 1 )
    								{
    									// set center of map
    									map.setCenter( bounds.getCenter() );
    									map.setZoom( 16 );
    								}
    								else
    								{
    									// fit to bounds
    									map.fitBounds( bounds );
    								}
    
    							}
    
    							/*
    							*  document ready
    							*
    							*  This function will render each map when the document is ready (page has loaded)
    							*
    							*  @type	function
    							*  @date	8/11/2013
    							*  @since	5.0.0
    							*
    							*  @param	n/a
    							*  @return	n/a
    							*/
    							// global var
    							var map = null;
    
    							$(document).ready(function(){
    
    								$('.acf-map').each(function(){
    
    									// create map
    									map = new_map( $(this) );
    
    								});
    
    							});
    
    							})(jQuery);
    							</script>		
    						<div class="text_block">
    							<h3><?php the_sub_field('contact_location_name');?></h3>
    							<p><?php the_sub_field('contact_location_address');?></p>
    						</div>
    					</div>			   
    				<?php endwhile;?>
    			<?php endif;?>
  • Hey @hube2

    Thanks for your help here. I am just touching back on this now. I put my repeater and date fields in the two specified areas, along with the_title in the loop area so my code looks like this:

    <?php // get relationship field without formatting
    // returns an array of post ID values
    $posts_ids = get_field('seminars', false, false);
    // do your own query to order the posts
    $args = array(
      'post_type' => 'any',
      'posts_per_page' => -1,
      'post__in' => $post_ids,
      'meta_query' => array(
        'date_clause' => array(
          'key' => 'event_time',
          'value' => 'EXISTS'
        ),
      ),
      'orderby' => array('date_clause' => 'ASC');
    );
    $custom_query = new WP_Query($args);
    if ($custom_query=>have_posts()) {
      while ($custom_query=>have_posts()) {
        $custom_query=>the_post();
        the_title();
      }
    }
    wp_reset_postdata();
    ?>

    However I get a php error at this line:
    'orderby' => array('date_clause' => 'ASC');

    [08-Oct-2018 14:29:58 UTC] PHP Parse error: syntax error, unexpected ‘;’, expecting ‘)’ in /home/clientname/public_html/wp-content/themes/mytheme/template-parts/content-attorney.php on line 182

    I’ve been playing find the syntax error with no luck. Anything glaringly obvious to you?

  • If you are sure that you’ll only ever use the first row of the repeater then the meta key for your first date sub field will always be event_dates_0_event_dates_date

    As a side note, because of the way ACF names field you don’t need to name your sub field event_dates_date and you can just shorten that to date and this would result in the first row always having the meta key of event_dates_0_date

  • Nevermind just figured it out, I nested the forloops

    Heres my code if it helps someone else, just trying to stop it from returning values that dont relate to the current post:

    function acf_event_cost_options( $form ){
    
        foreach ($form['fields'] as &$field) {
    
            if(strpos($field->cssClass, 'acf_event_cost_options') === false)
                continue;
            //This only auto-populates a field which has the class dynamicfield. If it doesn't then, continue ! Don't forget to add a class to the field you want to dynamically populate in your form.
    
            global $post;
            $id = $post->ID; 	//  Important - this is what tells the form to only use values from the individual post, not all posts
    
            global $wpdb;
            $rows_name = $wpdb->get_results($wpdb->prepare(
                "
                SELECT *
                FROM wp_postmeta
                WHERE post_id = %d AND meta_key LIKE %s 
                ",
                $id,
                'event_cost_structure_%_option_name'  //enter the actual name of your repeater field and sub-field names, the % is a variable that represents the row number
            ));
    
            $rows_price = $wpdb->get_results($wpdb->prepare(
                "
                SELECT *
                FROM wp_postmeta
                WHERE post_id = %d AND meta_key LIKE %s 
                ",
                $id,
                'event_cost_structure_%_option_price'  //enter the actual name of your repeater field and sub-field names, the % is a variable that represents the row number
    
            ));
    
            $choices = array(array('text' => 'Please Choose an Option', 'value' => ' ', 'price' => ' '));
            //Default choice for dynamic select field. Value is blank, so if it's required it won't validate, change the text to what you want it to be, e.g. 'Please Choose:'
    
            if( $rows_name || $rows_price ) {
                foreach ($rows_name as $row_name) {
                    foreach ($rows_price as $row_price) {
                        //If there are results, for each result, find the 'repeater row number'
                        preg_match('_([0-9]+)_', $row_name->meta_key, $matches);
    
                        $meta_key = 'event_cost_structure_' . $matches[0] . '_option_name';
                        $value = get_post_meta($post->ID, $meta_key, true);
                        //Get the subfield value from the row.
    
                        //If there are results, for each result, find the 'repeater row number'
                        preg_match('_([0-9]+)_', $row_price->meta_key, $matches);
    
                        $meta_key_price = 'event_cost_structure_' . $matches[0] . '_option_price';
                        $value_price = get_post_meta($post->ID, $meta_key_price, true);
                        //Get the subfield value from the row.
    
                        $choices[] = array('text' => $value . ' $' . $value_price . '.00', 'value' => $value, 'price' => $value_price);
                        //Create an option array for each subfield value.
                    }
                }
            }
    
            $field->choices = $choices;
            //Once we've looped through all of the subfields values and created all of our options, we assign the $choices array (which has all of our new options) to the $field choices property.
    
        }
    
        return $form;
        //Display the new dynamically populated form.
    }
  • For your first issue, groupings are treated similar to repeater fields but there is a single row of data in that value.

    Visually, it appears as a repeater within a repeater.

    <?php
    
    // Check for grouping.
    if ( have_rows( 'price_information' ) ) :
    	while ( have_rows( 'price_information' ) ) : the_row();
    
    		// Check for repeater.
    		if ( have_rows( 'event_cost_structure' ) ) :
    
    			// Loop through the rows of data.
    			while ( have_rows( 'event_cost_structure' ) ) : the_row(); ?>
    
    				<p><?php the_sub_field( 'option_name' ); ?> : <?php the_sub_field( 'option_price' ); ?></p>
    
    			<?php
    			endwhile;
    		endif;
    	endwhile;
    else :
    	// No rows found.
    endif; ?>

    For the second issue, it seems to format the date correctly on my end…What are your organizations and settings in regards to the display/return format for the Date Picker?

  • I’m with @nathanaelphilip on this one. Rolling your own chat system is probably not the way I’d go. There are already plugins for integrating chat into WP, like this one https://wordpress.org/plugins/wp-live-chat-support/

    As far as cons for using ACF repeater fields, or ACF at all…

    ACF is a great plugin but it has it’s limitations. Performance of ACF on a high traffic site where you’d need to store thousands of messages in the meta table would likely (eventually) crash the entire thing. You have to remember that ACF uses WP core built in meta table and meta functions for data storage and retrieval and it is the core functionality of WP meta that actually creates the limitations of ACF. ACF is tool for creating admin pages that are easy to use.

    Think about what you would need to do in WP if you didn’t have ACF just using update_post_meta() and get_post_meta(). Not to mention that every chat string would need to have it’s own “Post” with related information about who is allowed to access it. What would hundreds of thousands of posts do to WP?

    There is also the problem you mentioned of two or more people trying to update the same information at exactly the same time. I’d assume that this would be rare, but if you tried to perform to updates to the database at the same time, to be honest, I don’t know what the results would be. You could either loose a message or end up with DB errors that crash one side of the conversation.

    This site does not even use ACF for this forum. It uses BBPress with some modifications done using ACF.

  • You probably saw this coming, but the answer to all your questions is “It depends”.

    I have been using ACF for so long that I do not remember a site I’ve built without it. Every site I build for a client is custom based on their needs.

    1. Is there anything like too many ACF fields? Or you always recommend to use ACF.

    The answer to this one is Yes. But mostly this has to do with repeaters and flexible content and saving the post. The number of ACF fields will rarely impact the performance of the front end of the site.

    When you have a lot of repeaters and flex fields, and depending on what types of fields you are using, the number of fields can impact the performance of the admin in 2 ways.

    The first is that the loading of the post editor could be slow when there are a lot of fields that depend on JavaScript, like any of the jQuery fields, this also includes WYSIWYG fields that depend on tinyMCE. When building complex field groups it is important to take advantage of the “Delayed Initialization” provided by some of the ACF fields.

    The second way that it effect the performance of the admin is when saving a post. There is a point where the save process can time out.

    I’ll give you an example of this. I once built a site for a client that had a repeater. Each row of the repeater had 7 WYSIWYG fields. The content of the page required specific formatting for layout out these content fields in a very structured way to meed the client’s requirements. All went well until the client decided to add 30… let’s call them “Panels” to one page of the site. This meant that ACF needed to save 210 WYSIWYG fields and related fields for determining other options. What happened was that the save took longer that 30 seconds, which meant the the browser timed out and it appeared that it crashed the site. (In reality, it was just the browser timing out. The update went merrily on it’s way in the background and completed successfully. When this happens you can wait a minute or 3, use the browser back button and then refresh the editor and all of the changes would appear.) It was because of this that I built this https://github.com/Hube2/acf-prevent-timeouts.

    When building something for a client using ACF it is important to think about how the client can abuse your masterpiece. I did not know that this problem existed when I built this site, but knowing it now I would not build another one the same way. I would likely use a post type using a parent page/post and child pages/posts in order to break things up and therefore avoiding the issue.

    2. When certain layout becomes too complex with tiny fields for everything, do you still use ACF or you look for page builder options in such scenarios?

    I have never used a page builder. I’ve found that they are too generic. They also rarely meet the specific requirements of my clients. Like I said, I build custom sites to exactly match the client’s needs. ACF allows me to do this without trying to shoehorn them into something that may not be exactly what they wanted. I also find that most page builders are bloated and also give the client too many options that allow them to break things easily. When using ACF I can give them only the options that they need. It makes my life easier because it’s harder for them to break things. And it makes their life easier because there is less for them to learn in order to manage their own site. My goal, when building a site is to turn it over to the client and for them to be able to do everything they need. The last thing I ever want to do is manage the content of a client’s site or need to make changes because they cannot understand how to do it themselves.

    3. Finally, lets say you are working on a blog. And at some point you want some custom structures in the middle of article, maybe a table or some other layout. How do you approach it? Do you create ACF templates and split up content area with repeater field so you can use these custom structures in the middle of articles? Or again do you take some other approach?

    The answer to this one is the biggest “It Depends” answer.

    For a blog… meaning “Blog Posts”. for this they usually get just the standard WP editor. Blogs are free form and all content and formatting inside of “The Content” area is up to the client. I may provide other options on the blog, for example a way to allow them to specify a banner image for the page, or some special feature. However, I will never build a way that requires special formatting and layout within this area.

    For the rest of the site. For example, page layouts and custom post types. These are almost always formatted specifically. Meaning that every page must look the same as every other page with set features. These features may be optional on each page, but when they appear they will always be shown in the same place and always appear the same when shown. These pages, templates and post types will have fields for everything that the client should be able to control. Outside of the blog, almost all of my clients require that the structure of specific pages be the same and meets there companies style guide. I may need to build them many specific templates for different page layouts. On occasion I also have included a generic page where the content is just a basic content field where they can control the layout, but this is rare and the client that wants this is usually familiar with WP and the use of things like shortcodes and editing HTML directly.

    In the case you mentioned about a “blog” with custom structures in the middle of the content. If this was a requirement given to me by the client I would likely give them 2 content editors, one for the beginning of the blog and one for the end and the other fields in the middle and it would be up to them do decide where this special feature would be inserted. The other option would be to build a custom shortcode so that they can insert the special features into their page. But like I keep saying, that would depend on the client’s specific needs.

  • As long as $team_code is a post ID (Integer) that represents the post you want to set the field and $post_id is the post ID of the post where you want to set this value and you use the field key for the field and this field is not some type of a sub field, like a field in a group field, or a clone field, or a repeater or flex field then

    
    update_field($field_key, $team_code, $post_id);
    

    should be updating the field.

    If the field is being set in the DB and your not seeing it on the front end, do you see this change in the admin?

    Do you have any caching plugins installed that would prevent this change being reflected on the front end?

  • I have this code example for a project if it helps (it’s not WP_Query but get_posts, seance is my custom post type, seances a repeater field and film is a relationship field) :

    <?php 
                            $today = date("Ymd");
                            $date = strtotime($today);
                            $seances = get_posts(array(
                                'suppress_filters' => FALSE,
                                'post_type' => 'seance',
                                'meta_key'  => 'date',
                                'orderby'   => 'meta_value_num',
                                'order'=>'ASC',
                                'meta_query' => array(
                                    'relation'      => 'AND',
                                    array(
                                        'key' => 'seances_%_film', // name of custom field
                                        'value' => '"' . get_the_ID() . '"', // matches exaclty "123", not just 123. This prevents a match for "1234"
                                        'compare' => 'LIKE'
                                        ),
                                     array(
                                        'key'       => 'date',
                                        'compare'   => '>=',
                                        'value'     => $today,
                                    )
                                    )
                                ));
                        ?>

    And in functions.php

    function my_posts_where( $where ) {
        global $wpdb;
        $where = str_replace(
                  "meta_key = 'seances_", 
                  "meta_key LIKE 'seances_",
                  $wpdb->remove_placeholder_escape($where)
        );
        return $where;
    }
     
    add_filter('posts_where', 'my_posts_where');
  • Within the events repeater, all of your field names except the one that is working use dashes in their field key names vs. underscores. Underscores are the default structure so I would check to make sure your variables are calling correct field names and it shouldn’t be event_date, event_name, etc. vs. event-date, event-name like you have.

  • You could go back to using the Date Picker and use JavaScript and JQuery to disable the fields.

    Here’s some code that I used in a recent project to do that, which demonstrates how to Disable various field types (Date Picker, Button Group/Radio Buttons, Select, Textarea, Repeater, WP Title)…

    
    /* START: Prevent editing of Support Ticket fields for specific roles */
    function cc_prevent_editing_support_ticket_fields_after_publish() {
      global $pagenow;
      if ( !is_admin() ) { return; } // only in wp-admin
      if ( $pagenow=='post-new.php' ) { return; } // not for 'new posts'
    
     // only for specific post type(s)
      $post_types = array('supporttickets');
      if ( !in_array( get_post_type(), $post_types ) ) { return; }
    
     // only for specific role(s)
      $user = wp_get_current_user();
      $user_role_id = $user->roles[0];
      $exempt_roles = array('administrator', 'owner', 'controller');
      if ( !in_array( $user_role_id, $exempt_roles ) ) {
    ?>
    <script type='text/javascript'>
      ( function ( $ ) {
        $( document ).ready( function () {
          $('#idOfDatePicker .acf-date-picker .hasDatepicker').prop('disabled','disabled'); // disable 'Date Picker' field
          $('#acf-field_59d9867971a81').prop('disabled','disabled'); // disable 'Select' field
          $('input[type="radio"][name="acf[field_59d94c7897682]"]').prop('disabled','disabled'); // disable 'Button Group' or 'Radio Buttons'
          $('#title').prop('disabled','disabled'); // disable WordPress Post Title
          $('#acf-field_59d968a0dc7a7').prop('disabled', true); // disable 'Textarea' field
          $('.acf-field-59daa7de17e69 .acf-actions').hover(function() {
            $(this).css('display','none');
          }); // removes delete button from 'Repeater Rows' on 'hover'
          $('.acf-field-59daa7de17e69 .acf-actions').css('display','none'); // removes delete button from 'Repeater Rows'
          $('.acf-field-59daa7ae17e68 a[data-event="add-row"]').remove(); // remove 'Add Row' button for 'Repeater' field
          $('.acf-field-59daa7ae17e68 a[data-event="remove-row"]').remove(); // remove 'Remove Row' button for 'Repeater' field
        });
      }( jQuery ) );
    </script>
    <?php
      }
    }
    add_action( 'edit_form_advanced', 'cc_prevent_editing_support_ticket_fields_after_publish' );
    /* END: Prevent editing of Support Ticket fields for specific roles */
    

    Hopefully that helps… you can target any HTML element in various ways and disable them. You can even add a specific ID or Class to your Date Picker fields in the Edit Fields screen for the field (next to ‘Wrapper Attributes’), and then target it that way (like I did at the top of JavaScript).

    ‘Disable’ is essentially the same as ‘Read Only’ for most purposes. However, when creating a *new* post, and you give a field a default value AND disable it, the value won’t Submit. So, if you are doing that… you will need to add more JavaScript that re-enables the form field upon click of the Submit button.

    At any rate, the above should get you going if you want to disable fields other than just the Basic fields.

  • Hi @mrspabs

    Below is some code cleaned up a bit. I am assuming that 2006 is your Post ID? You don’t need to pass that to sub fields of your repeater, but it doesn’t hurt.

    I just added an extra bit to the ‘while’ statement making sure to only loop 3 times. I created the iteration variable just above the while statement with a value of 0. I then increment that value at the end of the while. Hope this helps! Please mark this thread as resolved if so, otherwise please reply with more questions.

    <?php
    date_default_timezone_set( 'America/Los_Angeles' );
    $today = date( 'Ymd' );
    if ( have_rows( 'events', 37 ) ) {
    ?>
    <ul>
    <?php
      $i = 0;
      while ( have_rows( 'events', 37 ) && $i<4 ) {
        the_row();
        $expire = get_sub_field( 'expire_on' );
        if ( $expire > $today ) {
    ?>
    <li class="eventrow event<?php echo get_row_index(); ?>">
      <h3>
        <a target="_blank" href="<?php the_sub_field( 'events_link' ); ?>">
          <?php the_sub_field( 'events_title' ); ?>
        </a>
      </h3>
      <p>
        <?php the_sub_field( 'events_date' ); ?><br />
        <em><?php the_sub_field( 'events_location' ); ?></em>
      </p>
    </li>
    <?php
        }
        $i++;
      }
    ?>
    </ul>
    <?php
    }
    ?>

    p.s. Thanks for teaching me about the get_row_index() function!

  • Solved!

    Since it’s in an repeater, it needed to be;

    $date = get_sub_field('event_date', false, false);

    instead of “get_field” it needed to be “get_sub_field”

  • I know this is an old post but it is exactly what I need to do. I am using a date and time picker field for both start and end of an event. I need to make it so that the end date and time can only be after the start date and time. I have googled for hours trying to find a solution but this one is as close as i have gotten. What i could really use is an elaboration on your suggestion.

    I am currently using a repeater field with start and end fields. What else would you need to assist me in this, or can you recommend a place for me to look. Thank you so much for helping me out.

  • This functionality has recently been added to the checkbox field, it was originally only part of the radio field. I imagine that eventually it will find it’s way into the select field as well.

    In the mean time, a work-a-round

    Create your select field that has a choice of “Other”
    Create a text field with conditional logic to show if “Other” is selected for the choice.

    That’s the easy bit.

    For the saving of the new value as a choice I would recommend looking at the code that does this for the checkbox field

    
    // FROM advanced-custom-fields-pro/fields/checkbox.php LINE 368 
    
    // save_other_choice
    if( $field['save_custom'] ) {
      
      // get raw $field (may have been changed via repeater field)
      // if field is local, it won't have an ID
      $selector = $field['ID'] ? $field['ID'] : $field['key'];
      $field = acf_get_field( $selector, true );
      
      
      // bail early if no ID (JSON only)
      if( !$field['ID'] ) return $value;
      
      
      // loop
      foreach( $value as $v ) {
        
        // ignore if already eixsts
        if( isset($field['choices'][ $v ]) ) continue;
        
        
        // unslash (fixes serialize single quote issue)
        $v = wp_unslash($v);
        
        
        // append
        $field['choices'][ $v ] = $v;
        
      }
      
      
      // save
      acf_update_field( $field );
      
    }    
    

    basically, you need to get the current field, update the choices with your addition and then call acf_update_field().

  • Hi @britta , please, can you post your complete solution to @b1naryb0y original question ? I can’t understand what you made to get working.

    Me, I had to take an alternative approach.

    The following code will never work for repeater fields:

    $args = array (
    		    'post_type' => 'event',
    		    'meta_query' => array(
    			    'relation'		=> 'AND',
    				array(
    			        'key'		=> 'event_dates_%_start_date',
    			        'compare'	=> '<=',
    			        'value'		=> '20150524',
    			    ),
    			     array(
    			        'key'		=> 'event_dates_%_end_date',
    			        'compare'	=> '>=',
    			        'value'		=> '20150524',
    			    )
    		    ),
    		);

    As suggested by @mediawerk , event_dates_0_start_date AND event_dates_1_end_date accomplish the start before testdate and end after testdate.

    So I replaced it with:

    array(  
                  'key' => 'opening_dates',
                  'value' => 20150524,
                  'compare' => 'LIKE'
                 ),
    			

    The 'opening_dates' postmeta field contains all the single dates resulting from the repeating “start_date"/"end_date" couple and it was created with this code of mine placed in functions.php using the "acf/save_post" hook:

    
    	function create_opening_dates_array_when_saving_post_with_repeating_start_end_dates($post_id) {
    	
    	
    		// bail early the post type to apply
    		// src: https://support.advancedcustomfields.com/forums/topic/acfsave_post-action/
    		$post_type = get_post_type($post_id);
    			if ($post_type != 'event' ) {
    				return;
    			}
    			
    			
    			// not used here
    			$fields = $_POST['acf']; 
    			
    			// $intervals will contain the interval couples: ['single_interval']=> array("20170301", "20170320")
    			$intervals = array();
    			
    			
    			// 
    			// loop repeater fields
    			if( have_rows('event_dates') ):
    			
    			 	// loop through the rows of data
    			    while ( have_rows('event_dates') ) : the_row();
    			
    			       // for each row, get the "from" "to" couple and save it in the "single_interval" key (array) in the intervals array
    			       $from =  get_sub_field('start_date', false, false);
    			       $to =  get_sub_field('end_date', false, false);
    			       $intervals[]['single_interval'] = array($from, $to);
    
    			
    			    endwhile;
    			
    			else :
    			
    			    // no rows found
    			
    			endif;
    			 
    		// here will be saved the opening date vales	
    		$final_array = array();
    
    		 // loop the array containing the couples of intervals
    		 foreach($intervals as $single_interval) {
    			 
    			 // $intervals = array("20170301", "20170320")
    			 foreach($single_interval as $intervals) {
    			 	
    			 	// fill in missing in-between dates...
    				$arrays_of_single_dates = getDatesFromRange($intervals[0], $intervals[1]);
    				
    				// loop the resulting array and save each single value in the final array...
    				foreach($arrays_of_single_dates as $single) {
    					$final_array[] = intval($single); // from string to integer
    				}
    			}
    		
    		};
    	  // var_dump($final_array);
    	  
    	  
    	  // create or update a meta_key field called "opening_dates" and set as meta_value the $final_array containing all the opening dates
    	  update_post_meta( $post_id, 'opening_dates', $final_array);
    
    	 // var_dump($final_array);	  
    	};
    
    	
    	add_action('acf/save_post', 'create_opening_dates_array_when_saving_post_with_repeating_start_end_dates', 1);
    

    I’ve got the getDatesFromRange function from here.

    I wonder if @Elliot knows a simpler and better performing solution anyway…

  • You are right, there isn’t any way to do this using WP_Query. Doing this on the event date archive is going to be extremely complicated. Well, doing it anywhere is going to be complicated because event category is not really related to the event date except through the event.

    Doing this with just the basic function that WP gives us you would need to… and I’m not sure about this

    1) Get all the even categories
    2) Get all the events in each category
    3) Somehow sort them by the event date and there isn’t any way to sort posts based on a field in another post

    What you need to be able to do is one WP_query on the events. The best way to accomplish this is to store all of the information you need to query as part of the event.

    I’ve posted several replies here about making repeaters easier to search and this is the same basic principle. You take information that you want and copy it to where it will help you the most.

    
    add_action('acf/save_post', 'make_events_filterable');
    function make_events_filterable($post_id) {
      if (get_post_type($post_id) != 'event') {
        // return;
      }
      // set up two fields to store the information
      // these need to have unique names that are different than the acf field names
      $category_field = 'event_category';
      $date_field = 'event_date';
      // delete anything that's currently stored in these two fields
      // to avoid creating duplicates
      delete_post_meta($post_id, $category_field);
      delete_post_meta($post_id, $date_field);
    
      // This is the complicated bit. You need to get the value the
      // category taxonomy field
      // and the date relationship field
      // loop through them, get the value you want to store from those locations
      // and then update the new post meta field with those values
      
          // start loop for a field
          // get value for the field
          add_post_meta($post_id, $field_name, $value, false);
          // false at the end means it can have multiple values
      
    }
    

    Now you can use these fields in WP order by clauses in the meta query to order your event posts by category and date https://make.wordpress.org/core/2015/03/30/query-improvements-in-wp-4-2-orderby-and-meta_query/

    With them in the right order you can loop through them and output new category and date headings when they change.

    Hope some of this helps.

  • The first thing that I would do is store these event dates into something that can more easily be searched in a simple meta_query, like I said above, searches based on repeater sub fields are a PITA that I avoid.

    
    <?php 
      
      // step 1: store event_date in a queryable form
      // this is done as a class, the reason is storage of
      // each value that has been saved
      class store_repeater_sub_field_in_standard_wp_meta {
        
        // this array will store values that have already been saved
        // more about this later
        private $fields = array();
        
        public function __construct() {
          // this is where we add the filters
          // use the field keys here because it is a sub field
          // this class will work on multiple fields by adding the
          // filter multiple times, once for each field key
          // all values stored into new fields will be identical to values stored by ACF
          add_filter('acf/update_value/key=field_123456', array($this, 'convert_sub_field'), 10, 3);
        } // end public function __construct
        
        public function convert_sub_field($value, $post_id, $field) {
          // get the field key
          $field_key = $field['key'];
          // get the field name
          $field_name = $field['name'];
          // create a new field name based on the current field name
          $queryable_name = 'queryable_'.$field_name;
          
          // first step is to see if we've already saved any values for this field
          if (!isset($this->fields[$field_key])) {
            // there is not value set in the property for this key
            // no values have been updated yet
            // clear any existing values from the queryable field
            delete_post_meta($post_id, $queryable_name);
            // add a nested array to the property to hold values
            // for this field, this will also ensure that we don't
            // delete them again since the field has a value in the property
            $this->fields[$field_key] = array();
          }
          // see if we've already saved this value for this field
          // there really is not point saving the same value twice
          if (!in_array($value, $this->fields[$field_key])) {
            // not there, add it the values
            $this->fields[$field_key][] = $value;
            // and add it to the database
            add_post_meta($post_id, $queryable_name, false);
            // the last argument above says that this is not a unique meta key
            // and will hold multiple values
          }
          // return the original value for ACF to process as normal
          return $value;
        } // end public function convert_sub_field
        
      } // end class store_repeater_sub_field_in_standard_wp_meta
      
      // instantiate the object
      new store_repeater_sub_field_in_standard_wp_meta();
      
    ?>
    

    I know that what is above can seem extreme, but this was fairly easy to do (if you remove all the comments there is actually very little code there) and now we can construct extremely simple queries instead of complex LIKE queries and adding filters to add LIKE to the meta_key part of the query because we are querying a sub field.

    
    // current date
    $current_date = date{'Ymd');
    // get the next event from now
    $args = array(
      'post_type' => 'event',
      'post_status' => 'publish',
      'posts_per_page' => 1, // or the number of next dates you want
      'meta_key' => 'queryable_event_date',
      'order_by' => 'meta_value',
      'order' => 'ASC',
      'meta_query' => array(
        'key' => 'queryable_event_date',
        'value' => $date,
        'compare' => '>='
      ),
    );
    $next_event_query = new WP_Query($args);
    

    during the loop for the “next_event” query, collect a list of posts show so that they are not returned in the next query.

    
    // other code before loop
    $events_shown = array();
    if ($next_event_query->have_posts()) {
      while ($next_event_query->have_posts()) {
        $next_event_query->the_post();
        $events_shown[] = $post->ID;
        // other code to display the next event post
      }
      wp_reset_postdata()
    }
    

    Then use the values collected in $events_shown to not get those events again

    
    $args = array(
      'post_type' => 'event',
      'post_status' => 'publish',
      'posts_per_page' => 1, // or the number of next dates you want
      'meta_key' => 'queryable_event_date',
      'order_by' => 'meta_value',
      'order' => 'ASC',
      'meta_query' => array(
        'key' => 'queryable_event_date',
        'value' => $date,
        'compare' => '>='
      ),
      'posts__not_in' => $events_shown,
    );
    $event_query = new WP_Query($args);
    

    I’m sure that you could also construct a single query and loop to do this, but I tend toward a less complex coding style that lets me more easily understand what I was thinking when I need to look at it again in a year because something needs to be changed.

    Hope this helps

  • To answer your question, I’m thinking it would be #2.

    Logically the event_date subfield would have to compare it’s date to today’s date and post the next upcoming event in the left column until that event date has passed. Once that has passed, then the next event date would post in the left column until it’s expiration. All other dates would be posting on the right.

    If ACF is going to be an issue with posting such a repeater in this manner, what would you recommend? A different plugin? A different ACF Field method?

  • The next event from the current event shown, or the next event in general?

    For example:
    1) you’re showing event A and the next one after this event is event B
    2) today is Nov 18 and the next event in Nov 20

    And now that I understand that you’re trying to query a sub field of a flexible content field, that just makes things more difficult. You can’t just query sub fields.

    Let’s say that the value you want is in the first row of the repeater or flex field, the actual meta key will be “repeater_field_name_0_event_date” or “flex_field_name_0_event_date” where the “0” represents the row number starting at zero.

    There is a section on this page that explains it https://www.advancedcustomfields.com/resources/query-posts-custom-fields/ and there are many topics here that talk about it. I will not be able to help you with this, because I avoid querying sub fields at all costs, it involves a ridiculous amount of work and testing to get it right that will constantly be breaking or need tweaking to keep it working.

    answer my first question and I’ll see if I can think of a work around for querying sub fields for what you want to do.

  • I’m trying to have on the left column the next upcoming event and have the other events post on the right column. The left column data is what’s missing. The right column data is not having a problem posting.

    <?php if( have_rows('tradeshows', 40) ): ?>
    //This is a repeater field, and I'm getting values from another post:
    //https://www.advancedcustomfields.com/resources/how-to-get-values-from-another-post/

    ‘event_date’ is a sub field. I’ve attached screenshots of my setup.

  • I’ve looked at your code a couple of times and to be honest, I can’t really figure out what you’re trying to do. This is your code with the white space cleaned up so I could see what’s going on a little better and some comments.

    
    <?php 
      if (have_rows('tradeshows', 40)):
        // this field is getting nothing
        // because there is no while(have_rows()) loop or call to the_row()
        // since $current_event_date has a value of NULL the query will not return anything
        // or maybe since the value is NULL it returns all posts
        // not really sure here
        $current_event_date = get_sub_field('event_date');
        $next_event_query = new WP_Query(array(
          'post_type'      => 'event',
          'post_status'    => 'publish',
          'posts_per_page' => -1,
          'meta_query'     => array(
          array(
            'key'        => 'event_date',
            'compare'    => '>',
            'value'      => $current_event_date,
          )
          ),
          'meta_key'     => 'event_date',
          'orderby'        => 'meta_value',
          'order'          => 'ASC'
        ));
        // not sure why we're getting this field here
        // this variable is never used
        $rows = get_field('tradeshows', 40);
        ?>
          <div class="trades">
            <?php 
              if ($next_event_query->have_posts()) : 
                // this is looping through the posts of the nested query
                // show values associated with those posts
                // if the query above returns nothing then this will never run
                while ($next_event_query->have_posts()): 
                  $next_event_query->the_post(); 
                  ?>
                    <div class="col-sm-3">
                      <h3>NEXT TRADESHOW</h3>
                      <p><?php echo $current_event_date; ?></p>
                    </div>
                  <?php 
                endwhile;
                wp_reset_postdata();
              endif;
            ?>
            <div class="col-sm-6 col-sm-offset-3">        
              <h3>UPCOMING TRADESHOWS</h3>
              <?php 
                while (have_rows('tradeshows', 40)): 
                  // this is looping through the original repeater
                  // to show subfield of this field for post ID = 40
                  the_row();
                  ?>   
                    <div class="col-sm-4">                       
                        <p class="eventdate"><?php the_sub_field('event_date'); ?><br />
                        <span class="locplace"><?php the_sub_field('event_location'); ?></span></p>
                    </div>                                                          
                  <?php 
                endwhile;
              ?>   
            </div>
          </div>                        
        <?php 
      endif;
    ?>
    

    Looking back over everything, I honestly can’t tell how the event date in post 40 is related to the “event_date” in your query where you’re trying to get the posts, or what type of field that is or how it should be queried. Is it another sub field of a repeater in those other posts? Is it a top level field? Why is <?php if( have_rows('tradeshows', 40) ): ?> looking at post ID 40 in the first place?

    The first thing you need to do is to go back to a point where the loop for the repeater is working, showing the current values of that repeater and then explain what it is you’re trying to query for in the other posts. Like I said, is it a top level field? is it a sub field of a repeater?

  • 1) To obtain a specific row by the value of its subfield, you have to iterate through all rows.

    function retrieve_row( $fieldNameOrArray, $subfieldName, $searchValue, $post_id = false ) {
    	
    	if ( is_array( $fieldNameOrArray ) )
    		$field =& $fieldNameOrArray;
    	else
    		$field = get_field( $fieldName, $post_id );
    	
    	if ( !$field || !is_array( $field ) || !isset( $field[0][ $subfieldName ] ) )
    		return false;
    	
    	foreach ( $field as $index => $row ) {
    		if ( $row[ $subfieldName ] == $searchValue )
    			return $row;
    	}
    	
    	return false;
    	
    }
    
    // Example
    $row = retrieve_row( 'repeaterFieldName', 'uniqueId', 'gold' );
    // Or if you already have the field loaded into a variable
    $row = retrieve_row( $repeaterFieldArray, 'uniqueId', 'gold' );

    To enforce unique values in a particular subfield, you need to place a script on the repeater field’s instructions:

    <script>
    jQuery( function() {
    	
    	// Definitions
    	
    	var repeaterFieldName = 'repeater',
    		uniqueFieldName = 'unique_id',
    		$repeaterFieldEl = jQuery( '.field.field_type-repeater[data-field_name="' + repeaterFieldName + '"]' );
    		
    	// Validation
    		
    	jQuery(document).on( 'acf/validate_field', function( event, $el ) {
    		
    		var fieldName = $el.data('field_name'),
    			fieldValue,
    			$uniqueFieldList,
    			$uniqueInputs;
    			
    		if ( fieldName != uniqueFieldName )
    			// Skip fields other than the unique one
    			return;
    		
    		fieldValue = $el.find('input[type=text], input[type=number]').val();
    		
    		if ( !fieldValue )
    			return;
    		
    		$uniqueFieldList = $repeaterFieldEl.find( '.row > .sub_field[data-field_name="' + uniqueFieldName + '"]' );
    		$uniqueInputs = $uniqueFieldList.find('input[type=text], input[type=number]');
    		
    		// Compare against other unique fields
    		$uniqueInputs.each( function( n, currentEl ) {
    			if ( $uniqueFieldList[n] === $el[0] ) {
    				// Skip comparing against self
    				return;
    			}
    			if ( currentEl.value == fieldValue ) {
    				// Not unique
    				$el
    					.data( 'validation', false )
    					.data( 'validation_message', 'This field must have a unique value.' );
    			}
    		});
    		
    	});
    	
    });
    </script>

    Just set the repeaterFieldName and uniqueFieldName at the beginning to something appropriate, and make sure that your unique field is required, or the validation will not run.

    2) Perhaps you should create another ACF group with those same fields and associate it to users. Now the fields will exist in the user meta. When you use update_field(), pass the field name, not the key, as the key is going to be different.

  • Your code does not make any sense to me at all, can’t really figure out what your doing.

    assuming that this is checking to see if a repeater has a value

    
    if(get_field('tradeshows', 40) ):
    

    you get a sub field of the current post, however, I do not see any have_rows() loops, so this should return false, unless this loop starts somewhere before the code you’ve included. https://www.advancedcustomfields.com/resources/have_rows/

    
    $current_event_date = get_sub_field('event_date');
    

    Then you do a query based on that value, after the query you have

    
    $rows = get_field('tradeshows', 40);
    $tradeshowslocation = get_sub_field('event_location', 40);
    

    which is getting the value for the same field you checked to make sure it had a value and then you’re getting a sub field of that repeater, but once again, I don’t see any have_rows() loop.

    Then you start looping through your custom query

    
    <?php if ($next_event_query->have_posts()) while ($next_event_query->have_posts()): $next_event_query->the_post(); ?>
    

    At this point, any calls to ACF functions will assume that the post you want to get values from is this post from the custom query and not the original post you were getting values from before the loop. At the same time you’re not even trying to get any values from this new post to display them.

    Your code should go in a sequence that looks something like this, that is if you are looping through a repeater to get information for doing the query.

    
    if (have_rows('repeater')) {
      while (have_rows('repeater')) {
        the_row();
        $current_event_date = get_sub_field('event_date');
        // do your custom query
        // .........
        if ($next_event_query->have_posts()) {
          while ($next_event_query->have_posts()) {
            $next_event_query->the_post();
            // get values and display information about this post
            // of the custom query
          } // end while have posts
          wp_reset_postdata(); // important
        } // and if have posts
      } // end while have rows
    } // end if have rows
    
Viewing 25 results - 201 through 225 (of 270 total)