Ordering foreach loop by custom date field set in Blueprint

first-time
admin

#1

Is there a way to order my forloop by a custom field in my Blueprint. I see you can order by date but if I have a custom Date field, can I use that instead?

for example:

Blueprint

header.overview.datestart:
          type: datetime
          label: Start Date #PLUGIN_ADMIN.DATE
          toggleable: true

Front End

{% set this_year = "now"|date('M d Y') %}
        {% set event_date = feature.header.overview.datestart|date('M d Y') %}
       
        {% for feature in page.find('/events').children().order('event_date').slice(0, 3) %}
           {{ event_date }}
           
            <li>
            {{ feature.title }}
            {{ feature.header.overview.datestart|date("M d Y") }}
            </li>
            
{% endfor %}

#2

Update:

So after thinking it over I used the Blog Recipe as a guide:

FrontEnd

{% for feature in page.find('/events').children().slice(0, 3) %}
   <li>
            {{ feature.title }}
            {{ feature.header.overview.datestart|date("M d") }}
   </li>
{% endfor %}

Now I need to order the loop by feature.header.overview.datestart; I know there is an .order() parameter but its not working to order by datestart

{% set this_year = "now"|date('Y') %}
{% for feature in page.find('/events').children.order('feature.header.overview.datestart', 'desc').slice(0, 3) %}
           
    <li>
       {{ feature.title }}
       {{ feature.header.overview.datestart|date("M d Y") }}
    </li>
      
 {% endfor %}

The above spits out the events and date but not in the order I need them in.


#3

Update:

So this is the latest, it outputs the data i need just not in the order. Its ordering the data by default ordering of the page

{% set this_year = "now"|date('M d Y') %}       
        {% for feature in page.find('/events').children().slice(0, 3) if feature > this_year %}
           
            <li>
            {{ feature.title }}
            {{ feature.header.overview.datestart|date("M d Y") }}
            </li>
            
        {% endfor %}

#4

is it no way to order by a custom date field?


#5

You could instead store your date as YYYY-MM-DD to make comparison easier.
Then you have to adjust your if to if feature.date|date(‘Y-m-d’)
Example:

{% set this_year = "now"|date('Y-m-d') %}   
{% for feature in page.find('/events').children().slice(0, 3) if feature.date|date('Y-m-d') > this_year %}
       
        <li>
        {{ feature.title }}
        {{ feature.header.overview.datestart|date("M d Y") }}
        </li>
        
    {% endfor %}

#6

Hmm, I don’t think this will get the results I’m looking for @paul unfortunately.

I need the comparison to be based off the custom date field and not the default date field. Right now your example results to nothing outputting. The feature.header.overview.datestart needs to be in the equation some type of way i believe.

These are the Datefields I’m using for my events. There is a Date Start and a Date End.

                 columns:
                    type: columns
                    fields:
                        column.start:
                            type: column
                            fields:
                    
                                header.overview.datestart:
                                    type: datetime
                                    label: Start Date #PLUGIN_ADMIN.DATE
                                    toggleable: true
                                    help: PLUGIN_ADMIN.DATE_HELP
                                    style: vertical
                                    size: medium

                        column.end:
                            type: column
                            fields:
                                
                                header.overview.dateend:
                                    type: datetime
                                    label: End Date #PLUGIN_ADMIN.DATE
                                    toggleable: true
                                    help: PLUGIN_ADMIN.DATE_HELP
                                    style: vertical
                                    size: medium

On the front end I want to Pull the latest 3 Events based on Today’s Date – the Now. That way when one event ends, the next event will populate this loop – So the latest 3 events will always show. Is there a way to do this without doing something really hackie?


#7

well, then you slice filter si not at its place.
First step would be to get only future date, and second step would be to slice, or use anoher condition.
Regarding date, you can juste change page.date to page.header.yourcustomdate
Edited example:

{% set this_year = "now"|date('Ymd') %}   
{% for feature in page.find('/events').children() if feature.header.datestart|date('Ymd') > this_year %}
   {% if loop.index < 4 %}
    <li>
    {{ feature.title }}
    {{ feature.header.overview.datestart|date("M d Y") }}
    </li>
    {% endif %}
{% endfor %}

#8

@paul hold on, I can change the page.date to whatever? how so? That may be the easiest solution as I’m not using this template for a blog or to display a creation/publish date.

Also, I was thinking something similar that my slice might be in the wrong place. Your example however outputs the date in the default page order. It seems like the loop is ignoring the if statement or ignoring the custom field entirely and spitting out the data of the children pages, and constraining the data to just 3 events. Its basically doing everything but ordering it. However, if I can just replace the page.date, that may be the solution I need.


#9

Its basically doing everything but ordering it.

well, then you need to order your page children. Example:

{% set this_year = "now"|date('Ymd') %}   
{% for feature in page.find('/events').children().order('date', 'desc') if feature.header.datestart|date('Ymd') > this_year %}
   {% if loop.index < 4 %}
    <li>
    {{ feature.title }}
    {{ feature.header.overview.datestart|date("M d Y") }}
    </li>
    {% endif %}
{% endfor %}

I can change the page.date to whatever?

I’m not sure I understand your question here


#10

@paul

This is what I was referring to…

I tried setting the page.date to header.overview.datestart but that produces an error. I’m guessing this is a syntax error where you cant use a “.” for the variable.

{% set page.date = header.overview.datestart %}

But if I can replace the default date to the header.overview.datestart date, then that may resolve everything.


#11

yes, but you never use page.date it in your twig, or am I missing something?


#12

isn’t the .order part of this loop simply using page.date?

I mean I can reorder the pages manually in the admin and get the results I need but I’d hate to do this whenever an event starts/ends. Right now, the header.datestart and header.dateend fields I’m using to display the dates of the events. But I would like to use the .datestart field to order the events by the date stored in this field and not by the default date (created/modified). I guess its not possible to order these child pages by the .datestart field.

In PHP I can do this like so:

$feature_event = array(

	array(
		"title" 	=> "Event 1",
		"date" 		=> "July 27-29, 2018",
		"end"		=> strtotime("July 29, 2018"),
		"img" 		=> "images/featured-events/featured-event-1.jpg",
	),
	array(
		"title" 	=> "Event 2",
		"date" 		=> "July 6-8, 2018",
		"end"		=> strtotime("July 8, 2018"),
		"img" 		=> "images/featured-events/featured-event-2.jpg",
	),
	array(
		"title" 	=> "Event 3
		"date" 		=> "October 26-28 2017",
		"end"		=> strtotime("October 28, 2017"),
		"img" 		=> "images/featured-events/featured-event-3.jpg",
	),
	

);

usort(
	$feature_event,function($a,$b){
		return $a['end']-$b['end'];
	}
);



<h5>Upcoming Events</h5>
<?php $i=0; foreach($feature_event as $event): if ($i == 3) break; ?>
    <?php if($event["end"] > $now): $i++;  ?>
        <div class="event">
            <div class="event-img">
                <a href="<?php echo $event["link"]; ?>" title="<?php echo $event["title"]; ?>">
                    <img src="<?php echo $event["img"]; ?>" />
                </a>
            </div>
            <div class="event-content">
                <h5><?php echo $event["title"]; ?></h5>
                <p><?php echo $event["date"]; ?></p>
            </div>
        </div>
    <?php  endif; ?>
<?php endforeach;?>

I’m just trying to translate this over to twig…and twig as I understand it doesn’t use usort or break.


#13

oh, sorry, I missed the order(‘date’ …

but the answer is yes, you can replace with your field, such as
.order(‘header.datestart’, desc) and it should work.

If your page selection is that complex, you should instead use page collections, this would give you more control would you need to setup this differently in the future, and would be easier to use.


#14

@paul

I’m sorry I’m beating this post into a grave, I’m just trying to understand. So I’m looking into page.collections. Is the collection only established at the top of the page or could I do something like this:

          columns:
                type: columns
                fields:
                    column.start:
                        type: column
                        fields:
                
                            header.overview.datestart:
                                type: datetime
                                label: Start Date #PLUGIN_ADMIN.DATE
                                toggleable: true
                                help: PLUGIN_ADMIN.DATE_HELP
                                style: vertical
                                size: medium
                                content:
                                    items:
                                        '@page': '/events'
                                    order:
                                        by: date

I haven’t seen many examples/recipes for collections.


#15

@paul

ok after reading the doc again, page collections only work in front matter and not in your blueprint correct?

So essentially I would changing to expert mode in the admin to add this collection? or am I totally off base here.


#16

no, that’s it exactly.

Then, you can access it in twig with

{% for item in page.collection%}
    {{ item.title }}
{% endfor %}