Support

Account

Home Forums ACF PRO Sorting repeater fields by date

Solving

Sorting repeater fields by date

  • Hello,
    I’m using a repeater field and in the repeater I would like to use a date picker. I would like then to display the rows sorted by months. Something like that :

    <div class='month'>
    <div class='the month'>January</div>
    <div class='items'>...</div>
    <div class='items'>...</div>
    <div class='items'>...</div>
    </div>
    <div class='month'>
    <div class='the month'>February</div>
    <div class='items'>...</div>
    <div class='items'>...</div>
    </div>

    Is it possible?
    Thanks

  • Hi Soph,

    If you want to sort your repeater in frontend or in backend there is an ACF documentation here.

    Tell me if you need help to use it for your own case.

  • Hi feyfey,

    Thank you for your reply. I have to confess that I’m not very advanced in PHP. I understand the documentation on the link you provided, but I have no idea how to use it for my case.

    Could you help?

  • @soph I am not a beginner at PHP and I find array_multisort() overly complex, so don’t feel this is the problem. I find that using usort() is much more straight forward. The idea is that you create your own sorting function and call it with the array of the repeater and then use any of the fields on the row to determine the order. This is a basic example I posted here https://support.advancedcustomfields.com/forums/topic/sort-by-key-in-repeater-field/#post-49954, but I’ll repeat it

    
    // get the entire repeater in a multidimensional array
    $repeater = get_field('repeater');
    usort($repeater, 'sort_by_email');
    
    // usort function
    function sort_by_email($a, $b) {
      if ($a['email'] == $b['email']) {
        return 0;
      } elseif ($a['email'] < $b['email']) {
        return -1;
      } else {
        return 1;
      }
    }
    
  • Tell me if I get this right : using your code, I would have first to extract the month of each date, then use usort replacing email with month, right?
    Then I guess I would have to loop through each month to get the other fields?

  • What is the name of the repeater field and what is the name of the field you want to sort on?

    
    // get the entire repeater in a multidimensional array
    $repeater = get_field('YOUR-REPEATER');
    usort($repeater, 'SORT_REPEATER_BY_YOUR_SUB_FIELD');
    
    // usort function
    function SORT_REPEATER_BY_YOUR_SUB_FIELD($a, $b) {
      if ($a['YOUR-SUB-FIELD'] == $b['YOUR-SUB-FIELD']) {
        return 0;
      } elseif ($a['YOUR-SUB-FIELD'] < $b['YOUR-SUB-FIELD']) {
        return -1;
      } else {
        return 1;
      }
    }
    

    Once you’ve done the above then you loop over the array, in order to do this sorting you cannot use the acf have_rows() loop

    
    foreach ($repeater as $row) {
      // show items from this row
      // example, to echo one of the sub fields
      echo $row['SUB-FILED-NAME'];
    }
    
  • I would have a repeater with subfields : 1)date picker 2)title 3)texte

    I then want to to group each row by month to get something like this :

    Month1
    day1 – title1 – text1
    day2 – title2 – text2
    Month2
    day3 – title3 – text3

    I think maybe something’s missing still, I will try what you proposed and keep you updated!

    Thanks

  • The above code will just sort by the date field. More complex sorting can be accomplished. For example if you want to group all of the posts from a month without considering what year the date is in the you could use date functions on the field above the if statement and then base your if statements on the calculations of whatever manipulation you do to the values.

    Grouping by month is en entirely different issue and you need to do this grouping using PHP

    
    // set starting month and count
    // we need a counter to know if we're on the first row
    $previous_month = '';
    $count = 0;
    foreach ($repeater as $row) {
      // make sure that your date field is returning a valid date format
      // or this will not work
      $this_month = date('m', strtotime($row['YOUR_DATE_FILED']));
      if ($this_month != $last_month) {
        // month has changed
        if ($count > 0) {
          // close the previously opened container
          // the container is opened below
          ?>
            </div><!-- .month -->
          <?php 
        } // end in count > 0 (i.e. not first row)
        // open a new container and display the month
        ?>
          <div class="month">
            <div class="the_month"><?php echo $month; ?></div>
        <?php 
        
        // update previous month value for next loop
        $previous_month = $this_month;
    
      } // end if new month
    
      // output additional sub fields here
    
      // increment count
      count++;
      
    } // end foreach row
    
  • I updated the previous code, I had some things wrong, make sure you refresh.

  • Thank you for your help, I tried to use your code and it doesn’t seem to work quite yet. Also I made some modifications :

    <?php
    // get the entire repeater in a multidimensional array
    $repeater = get_field('agenda_test');
    // set starting month and count
    // we need a counter to know if we're on the first row
    $previous_month = '';
    $count = 0;				
    foreach ($repeater as $row) {
      echo "</br>";
      var_dump($row);
      // make sure that your date field is returning a valid date format
      // or this will not work
      $this_month = date('F', strtotime($row['date']));
      if ($this_month != $previous_month) {
         // month has changed
         if ($count > 0) {
           // close the previously opened container
           // the container is opened below						
           ?>
           </div><!-- .month -->
           <?php 
         } // end in count > 0 (i.e. not first row)
         // open a new container and display the month
         ?>
         <div class="month">
         <div class="the_month"><?php echo $this_month; ?></div>
         <?php
         // update previous month value for next loop
         $previous_month = $this_month;
       } // end if new month
       // output additional sub fields here
       // increment count
       $count++;
    } // end foreach row
    ?>

    And this what I get in return:

    array(2) { [“date”]=> string(10) “02/02/2019” [“texte_test”]=> string(42) “Premier texte de ce qu’il se passe ce mois” }
    February

    array(2) { [“date”]=> string(10) “15/02/2019” [“texte_test”]=> string(28) “Un autre texte pour février” }
    January

    array(2) { [“date”]=> string(10) “05/04/2019” [“texte_test”]=> string(53) “Un texte pour le mois d’acril, mais écrit avant mars” }
    May

    array(2) { [“date”]=> string(10) “10/04/2019” [“texte_test”]=> string(29) “Ce texte est pour le 10 avril” }
    October

    array(2) { [“date”]=> string(10) “02/03/2019” [“texte_test”]=> string(27) “Le jour de mon anniversaire” }
    February

    I guess I have to format the date in some way, though I don’t know how. Also, I want the months in french if possible….

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

You must be logged in to reply to this topic.