Support

Account

Home Forums General Issues List posts by date picker with pagination

Solving

List posts by date picker with pagination

    • Triphys

    • March 11, 2021 at 3:11 am

    Hello, I’m trying to solve a problem I have with a post page with events that have a certain date as a datepicker field. I would like to query these posts (events) and show the posts sorted by dates with the current month at the top.

    Right now I have been able to fetch the posts and sort them in the correct order. But I need some help with how I can paginate so that you see this month first and be able to go backwards for earlier months and forward for next months.

    I also need some help to group the posts by month so that I can put a label above the events for march for example.

    Maybe someone has done this before, or maybe it’s impossible or maybe someone could point me in the right direction? Because I’m not entirely sure of my next move.

    Thanks in advance.

    This is my current post page with loop:

    <?php
    	$args = array(
    		'post_type' => 'match',
    		'meta_key'  => 'date',
    		'orderby'   => 'meta_value_num',
    		'order'     => 'ASC',  
    	);
    	$loop = new WP_Query($args);
    	if ( $loop->have_posts() ) { ?>
    		<?php while ( $loop->have_posts() ) { $loop->the_post(); ?>
    			<p><?php the_title(); ?> - Event Date: <?php the_field('date'); ?></p>
    		<?php } ?>
    	<?php } ?>
    <?php wp_reset_postdata(); ?>
  • I am working on similar situation. Sorry, this got long. I thought that explaining it would lead me to a simpler solution but I’m still not seeing one.

    There is no easy way that I know of to have a url like http://yoursite.com/events/ and have a query the sorts all of the events in order and then jumps into the middle of the list somewhere where the current and future events are listed and then paginate both into the future and into the past.

    Sorry, I don’t really have any simple code that I can share.

    One option is to have a pre_get_posts filter. In this filter if the “page” query argument is not set then you attempt to find the page where the first current or future event is listed. Basically you have to do a query to get one post with a date >= today. Then you do a second query to get all of the posts sorted in the right order but return only an array of post IDs 'fields' => 'ids'. Then you get the index of this post in the array and set “page” query argument based on the results.

    
    $index = array_search($post_id, $query->posts);
    $page = intval($index/$posts_per_page)+1;
    

    I thought about this and discarded it. The reason why is that this only gives the page to show. The actual event that is current or future might be at the top, bottom or anywhere in between on this page depending on how many events there are and how many you are showing per page. Knowing the client I am working for this would not be acceptable. Not to mention that all of this additional querying will cause a performance issue if there are many events, which is likely to happen.

    Another option is the direction that I am going in, which is even more complicated.
    The first page is only going to show current and future events. I am adding a rewrite tag and rewrite rules for past events, in addition to all the date rewrite rules that I still need to work out because there will be date archive pages. In essence this will create two different urls for future vs past.

    
    add_rewrite_tag('%past%', '([^/]+)', 'past-events=');
    $rules = array(
      array(
        'rule' => 'event/past/?$',
        'rewrite' => 'index.php?post_type=event&past-events=1'
      ),
      array(
        'rule' => 'event/past/page/?([0-9]{1,})/?$',
        'rewrite' => 'index.php?post_type=event&past-events=1&paged=$matches[1]'
      )
    );
    foreach ($rules as $rule) {
      add_rewrite_rule($rule['rule'], $rule['rewrite'], 'top');
    }
    

    Then I am going to have a pre_get_posts filter that looks for this argument and causes WP to do a different query based on if this is set or not. Future events will be shown in ASC order and past events will be shown in DESC order.

    Then I’m going to build a custom pagination function where if you are on the first page of the upcoming events then “Older Events” will be a link to /event/past/ and if you are on the first page of past events “Newer Events” will be a link to /event/ (the main archive) to show upcoming events.

    I’m still in the middle of this and my client is complicating things further because they want a flag so they can decide what events actually show in the past. For example they have webinars so they want these to appear to make it easy for visitors to find old webinars. They also want a month (year) select field so this needs to be able to search all events past and future by date (year/month/day), but only showing past events that are flagged in the past while showing all future events. In addition to this they will have events that span multiple months so if say an event goes from March to May and they choose April, then this event also needs to appear in the results. And on top of this they want to be able to search by keyword, which should also show past and future events but past events must be limited to those that are flagged while all current and future events should be shown. I’m still in the process of working out all of these different queries and it’s making my head hurt.

    Luckily I already had all the other framework for events built for another client, only in that case they never wanted to show past events so I didn’t need to figure this out.

    • Triphys

    • March 11, 2021 at 8:36 am

    Thank you very much for your informative thoughts! Glad to see I’m not alone in this. Fortunately my client hasn’t (yet) complicated things further. But interesting to see what different ideas you’ve tried, the last one I thought about as well but unfortunately I don’t have the time nor the budget.

    But thanks to your message I came to think of another way to go which is a little bit different design-wise but I think it will work rather well. I will just load all posts and only show the ones with a date past today (or maybe a few days back as well). And then I will use Ajax to filter between older posts and newer posts based on dates. It’s just a thought right now but I’m guessing it might be able to work.

    I’m afraid it might not help you though 🙁

  • I stumbled on this discussion while looking for a similar solution. @hube2 would you be so kind as to share your already-created framework that doesn’t show past events? That is exactly what I’m looking for and I’m hoping your work can save me some time. Thanks in advance!

  • @bkmacdaddy the event framework I have is quite extensive and spans many, many files, classes and functions. It’s something that I’ve been working on for a couple of years and modified over time to meet client requirements. There are at least 3 different version now. It really is an entire application built into custom themes. It would be impossible for me to share the entire thing though this forum.

    If there are specific things that you need help with I can possibly help with them.

  • @hube2 I appreciate any help you can provide and totally understand your position regarding your framework and all the work that has gone into it.

    I have an “event” custom post type with the date picker field included. I’m using the following code in a page template to pull in the current month’s events, which is working fine. But I have no clue how to get this to paginate from month to month. What is needed is for the user to arrive on the page showing the current month’s events, then be able to click through to the next month’s events, and so on, including clicking back to the previous month but not past the current month. My guess is that I need to use WP_Query instead of get_posts, but still not sure how to get that to work.

    Again, any help you can provide is greatly appreciated!

    <?php
            $year = date('Y');
            $month = date('m');
            $posts = get_posts(array(
                'post_type' => 'event',
                'posts_per_page' => -1,
                'order' => 'ASC',
                'orderby' => 'meta_value',
                'meta_key' => 'date',
                'meta_query' => array(
                    'relation' => 'AND',
                    array(
                        'key' => 'date',
                        'value' => $year.''.$month.'01',
                        'compare' => '>=',
                    ),
                    array(
                        'key' => 'date',
                        'value' => $year.''.$month.'31',
                        'compare' => '<=',
                    )       
                )
            ));
            if( $posts ) : foreach( $posts as $p ) :
            $date_string = get_field('date', $p->ID);
            $date = DateTime::createFromFormat('Ymd', $date_string);         
            endforeach;
            ?>
            <div class="small-12 columns text-center">
                <h2><?php echo $date->format('F Y'); ?></h2>
            </div>
            <?php
            foreach( $posts as $p ) :
            $background_color = get_field('background_color', $p->ID);
                if($background_color == 'terracotta') {
                    $bkg = '#AD7A67';
                } elseif($background_color == 'sand') {
                    $bkg = '#C3AD93';
                } elseif($background_color == 'dark-blue') {
                    $bkg = '#2D4B62';
                } elseif($background_color == 'seafoam-green') {
                    $bkg = '#91ACA9';
                }
            $date_string = get_field('date', $p->ID); 
            $date = DateTime::createFromFormat('Ymd', $date_string);
            $name = get_the_title($p->ID);
            $start_time = get_field('start_time', $p->ID);
            $description = get_field('description', $p->ID);
            $event_page_link = get_field('event_page_link', $p->ID);
            $register_link = get_field('register_link', $p->ID);
            ?>
            <div class="large-3 small-12 columns">
                <div class="event section--one__content__event" <?php echo 'style="background-color:'.$bkg.';"'; ?>>
                    <?php
                    if($date) echo '<div class="name section--one__content__event__day">'.$date->format('j').'</div>';
                    if($name) echo '<div class="name section--one__content__event__name">'.$name.'</div>';
                    if($start_time) echo '<div class="name section--one__content__event__time">'.$start_time.'</div>';
                    if($description) echo '<div class="position section--one__content__event__description">'.$description.'</div>';
                    if($event_page_link) echo '<a href="'.$event_page_link.'" target="_blank" class="link section--one__content__event__link">EVENT PAGE</a>'; 
                    if($event_page_link && $register_link) echo ' <span class="link section--one__content__event__link">|</span> ';
                    if($register_link) echo '<a href="'.$register_link.'" target="_blank" class="link section--one__content__event__link">REGISTER</a>';
                    ?>
                </div>
            </div>
            <?php 
            endforeach; 
            
            endif; 
            ?>
    
Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic.

We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Cookie Policy. If you continue to use this site, you consent to our use of cookies.