[Drupal] Show Date header for a collection of nodes

Hi all

Continuing on from a recent post - I have a number of Drupal nodes (events) all with a date usually spanning over a one day period, example - Monday 8pm to Tuesday 3am. These events are being displayed as a big list or set LIMIT depending on the page.

I currently have a foreach loop inside a EFQ which displays all events.

This is generally the bulk of the code

  $nodes = array();

  if(isset($result['node'])) {
    $ids = array_keys($result['node']);
    $nodes = entity_load('node',$ids);
  }

  $build = array(
    '#prefix'=> '<div><ul>',
    '#suffix'=> '</ul></div>',
  );

  foreach($nodes as $node) {
    
    $build['node_'.$node->nid] = array(
      '#prefix'=> '<li>',
      '#suffix'=> '</li>',
    );
  
    $build['node_'.$node->nid]['field_event_date_and_time'] = array(
      '#type'=> 'markup',
      '#markup'=> '<strong>When:</strong> ' . date("g:ia", strtotime($node->field_event_date_and_time['und'][0]['value'])),
      '#prefix'=> '<div>', 
      '#suffix'=> '</div>',
      '#weight'=> 1,
    );
...

And with the above I get results like:

March 2014
Event 1
March 2014
Event 2
March 2014
Event 3

Monday 17th March 2014
Event 1
Monday 17th March 2014
Event 2
Monday 17th March 2014
Event 3

I now need a month title to group some of these events and a day title to group others.
I need to show the date header only once for a whole group of events, not for every event on the same day/month.

I need to produce something like:

March 2014
Event 1
Event 2
Event 3

April 2014
Event 1
Event 2
Event 3

and so on…

And also have the option to do things by the day

Monday 17th March 2014
Event 1
Event 2
Event 3

Tuesday 18th March 2014
Event 1
Event 2
Event 3

I’d like to place the title inside a <li> to continue the list if possible.
Can anybody help?

Thank you,
Barry

Can anybody offer any guidance on this?

Thanks

I don’t know Drupal and certainly not EFQ, hopefully there’s something for this 'built in"

If not, it can be done in PHP but it will probably take some datetime manipulation, array sorting, and a fair amount of logic.

I/m tired now, but if you can work out the exact logic you want into pseudo-code it will help. eg
get datetime
sort bymonth
then list events for that month ordered by …
etc. it will help a lot.

Ok Mittineague

I think there are Drupal functions/handlers to help with this though unsure myself at the minute. And a good learning exercise thanks.

What I think we need:

get datetime
do we have any events with this date
yes

  • print date once
  • loop and print events below
    no
  • move onto next day/month and repeat

Remember, the looping and printing events I mention above is already printing ok using the below code, I just need date wrappers to go around these events.

'#markup'=> l($node->title,drupal_get_path_alias('node/'.$node->nid))
...

'#markup'=> '<strong>When:</strong> ' . date("g:ia", strtotime($node->field_event_date_and_time['und'][0]['value'])),

So for example. If I have 100 events spread over 12 months each will be printed inside its own grouped date wrapper. Either by day or by month, or maybe both which is also very likely. I need to be flexible so things can easily be changed.

I already have an OrderBy statement inside my EFQ which hopefully should continue to work. We can ignore the ordering for now.

Hope this makes sense :cool:

Barry

Hey Barry,

I think you’re taking a more complicated direction with this than you need to (this goes back to my comment about Drupal making me lazy because it does everything for me)… This is so mind numbingly simple you’ll probably be a little unhappy with me for not catching on to what you had intended earlier so I could save you a lot of tinkering :smiley:

* This is going to take about ten times longer to jot down than to actually do within Drupal. I just did a proof of concept of it on a site I manage in less than 5 minutes.

1) Under your date/time you need to have a month/year format so go to Configuration -> Regional and Language -> Date and Time -> Formats. Add a “format” using: F Y. Then go to Configuration -> Regional and Language -> Date and Time and add a new “date type” called “Month Year” and use the new format that you just created.

2) I expect you already have a content type called “event” or something similar with a title, body and a date field right? You’ll need to create a simple view that lists out your events like so:



Monday 17th March 2014
Event 1
Monday 17th March 2014
Event 2
Monday 17th March 2014
Event 3


3) In your view, you have the date field and the title and maybe even the body field. In your field list (in the view) you’ll add second date field and use the following settings:

  • un-tick the Create a label checkbox
  • tick the Exclude from display checkbox
  • use the date and time formatter
  • under Choose how users view dates and times: select the new date type called “Month Year”
  • use the start date only if your field collects start and end dates
  • Save that up. I also add my own intuitive Administrative title (I’ll use “Month Settings Field” or something intuitive for my admin title) under the “More” setting and then rearrange my fields list so my new date field at the top. That way I know at a glance what field I’m using.

4) Now for the Magic!

  • Under format (left side of the views admin ui), you’re probably using “unformatted list” (the default) and that’s fine for our purposes.
  • Click the “settings link”
  • Under Grouping field Nr.1 choose your new field
  • Tick the “Use rendered output to group rows” checkbox
  • Tick the “Remove tags from rendered output” checkbox
  • Save your setting by clicking the “Apply” button

Now have a look at your results which should look like:


[B]March 2014[/B]
Monday 17th March 2014
Event 1
Monday 17th March 2014
Event 2
Monday 17th March 2014
Event 3


Go make a coffee and pat yourself on the back for a job well done :smiley:

hey, thanks awasson!

This is great and very good detailed information :slight_smile:
I understand this and just tried things and everything works good.

Unfortunately - the main reason I’m doing it this way is to use a EFQ over using Views.

Views is something I’ll look at in more detail, though for now I’m concentrating on EFQs and writing my own logic.

Cheers, Barry

Sounds good. Let me know if you change your mind and try a views version. Views really is a powerful tool when you need to do this sort of thing. It has it’s quirks and every now and again you need to nudge it with a little freestyle code but it was made for exactly what you’re doing here.

Andrew

Will do and thanks again Andrew :cool:

Can anybody advise on where to get started with some logic as outlined in post #4 ?

Maybe get started with something like

if(isset($node->field_event_date_and_time['und'][0]['value'])) {
        
}

Thanks, Barry