Jump to content
Nils Wiere

Events calendar strategies

Recommended Posts

For one of my projects, I'm currently building a small events calendar in ProcessWire. One requirement is that an event may have an unlimited number of associated dates. I tried two approaches, however each approach come with a difficulty:


1) One page per event with a repeater that holds the dates.

Page: Event 1

  • Text fields for shared event info
  • Repeater with a date field (e.g. Jan 1, Feb 1, ...)

Page: Event 2

  • Text fields for shared event info
  • Repeater with a date field (e.g. Jan 10, Jan 11., ...)

Problem: How can I get a chronological list with all events (dates + shared info) that is sorted like that:

  • Jan 1, Event 1 info
  • Jan 10, Event 2 info
  • Jan 11, Event 2 info
  • Feb 1, Event 1 info
  • ...

I know how to access repeaters, however all I got so far is a list structured like that:

Event 1 info

  • Jan 1
  • Feb 1

Event 2 info

  • Jan 10
  • Jan 11


2) A page with a page reference field from which the backend user shall be able to directly create child pages for each associated date.

Problem: What selector string do I need in the page reference setup, to make sure the new page is always created as child of the current page (no matter where that page lives in the backend structure)? Or is this only possible with custom PHP code in ready.php?


Would you consider one of those approaches a good strategy? If so, do you have any solution to my problems? If not, is there a better way? 

Share this post

Link to post
Share on other sites

I prefer the second approach, where the dates are what organize the events, so you can have something like this on the tree:


--- Calendar

------ 2017

---------- January (with page field to reference all events. And using https://modules.processwire.com/modules/connect-page-fields/ will help a lot)

---------- February...

------ 2018


--- Event 01 (with page field to reference all dates. And using https://modules.processwire.com/modules/connect-page-fields/ will help a lot)

--- Event 02 ...


So you can have URLS like:

List all events of 2017 – example.com/calendar/2017 

Show an event  – example.com/event-title  (the URL should not show the date as the event can happen anytime)

  • Like 1

Share this post

Link to post
Share on other sites

Actually, thinking about it more, this approach will only be good if are you planning to have other content on each month, like a page image, a description, etc.

If you only need to list all the dates where an event can occur, maybe it's better to use an Option field or the Textarea Profield.

Share this post

Link to post
Share on other sites

I also think a Page Reference field in conjunction with Connect Page Fields would be a good way to go. But not sure that you need a tree structure for the 'date' pages that is broken down into year, month, etc as per @Sérgio's suggestion. You could just have a single 'dates' parent and each 'date' page has a date field (you could create a pseudo-year/month/day structure for your event listings via URL segments if needed). In your 'event' page you select an existing date page if one exists or create a new date page as needed. The date pages are not children of the event pages but are connected to them via the two-way connection provided by Connect Page Fields.

Edit: one issue with this approach might be that as time goes on you could get a large number of date pages cluttering up the inputfield, and you couldn't do something like limit these to only future dates in the Page Reference field settings or else if you edited an old event the selected pages would be invalid. Maybe the autocomplete inputfield would be a good solution.

Alternatively, if you went with the Repeater approach you would do something like this:

  • Find all repeater 'date' pages by template, sorted by date (you may need check_access=0).
  • Foreach those date pages, getting the event pages associated with the date with getForPage().
  • If you wanted only a single date heading when their are multiple events on that date, in the foreach you would only output the date heading if it is different from the previous date heading.
  • Like 4

Share this post

Link to post
Share on other sites

Hi Sérgio and Robin,

thanks a lot for helping out. So the Connect Page Fields module seems to be interesting for the page reference approach – I'll check that out later today.

For now, I took the repeater approach, and your three bullets were essential in achieving the goal, @Robin S. That's how I do it:

1. I search for date repeaters by treating them as template  (by putting "_repeater" before the field name); I can now sort and limit the array to my tasting
2. I set "check_access=0" so that all users can see the results
3. I get field data from the page the repeater is living on by using the getForpage() method. 

$allEvents = $pages->find("template=repeater_event_repeater_datetime, event_datetime>today, sort=event_datetime, limit=14, check_access=0");		

foreach ($allEvents as $event):
	echo "<h4>$event->event_date</h4>";
	echo "<h5>{$event->getForpage()->event_title}</h5>";
	echo "<p>{$event->getForpage()->event_desc}</p>";

So far, that works great. Since there are some tricks involved I didn't know before, I'll keep checking, if there are any "side effects".

  • Like 6

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By t0b1
      Hello there, and thanks for ProcessWire!
      I'm getting to know ProcessWire while doing my first project using it and I really like it so far.
      The challenge I'm facing right now is the following:
      I have a One-Pager using fullpage.js, realized as a single PW-Page containing a Repeater Field where each Repeater Item is one Section.
      Some Sections are supposed to have a little menu at the Top which references/links to different Sections of the Website, so I wanted to use a Checkbox Field "Top Menu" to decide if a Section gets a Menu and a Page Reference Field to choose the different Sections (Repeater Items) it should contain.
      I've already accomplished this by pasting the following code into /site/ready.php:
      $wire->addHookAfter('InputfieldPage::getSelectablePages', function($event) { if($event->object->hasField == 'top_menu_entries') { $page = $event->arguments('page'); if($page instanceof RepeaterPage) $page = $page->getForPage(); $event->return = $page->; } });  
      The only problem that still remains is that when I select the Entry of the Repeater Item itself it doesnt save the selection, meaning after I saved it's unselected again.
      On some Sections I do want a Menu-Entry for the Section itself though (which would be styled differently and not link anywhere) for Continuity-Reasons, any ideas on how to achieve that?
    • By Anders
      I want to allow full text search on my site. There is a very nice solution that comes right out of the box:
      $selector = "title|body~=$q, limit=50"; This works, but to make it even better I would want to give higher weight to pages where the search term occurs in the title, than if it just occurs in the body. After all, a page with the title "Wine from France" is probably the best match for the search "france wine". How do I accomplish this in ProcessWire?
      I can see three possible paths, but I am not very fond of any of them:
      Do a direct SQL query, circumventing the API, along these lines. But I would prefer to abstract away the database layout if at all possible. Use something like ElasticSearch, but to be honest that would be to complicated to set up and maintain in the long run. Make multiple lookups, first for matches in the title, then for matches in the body, and merge and sort in PHP. My suspicion is that this would get complicated quite quickly. For instance, how do you deal with a page that has two of the three search terms in the title and the third in the body? Is there a magic option four I should look into? Or are any of the above options better than the others? Any input is welcome!
    • By iipa
      I have two Page Reference fields: Category and Subcategory. Category is parent of Subcategory, and can have 0 to n Subcategories. Fields are selected by dropdown selection.
      I'm trying to achieve following logic:
      1. Select Category (obviously works)
      2. Change Subcategory options based on selected Category (this works)
      3. Hide the Subcategory field if Category has no Subcategories (to prevent weird dropdown with nothing to select)
      I have tried to investigate two possible alternatives to achieve step 3:
      A) Make dynamic condition into Subcategory selection's "Only visible if..." field
      B) Make a hook that fires when Category changes, then hides Subcategory field if Category has no children
      So far I haven't been successful in either. Conditions I've tried always lead to hidden field, and I haven't been able to find set up a hook that fires on field change.
      So here's the question (finally): Is there a way to alter field visibility in API, for example in ready.php or inside a hook? In API I could loop through categories, find the ones that have children and then make a selector based on their IDs.
    • By schwarzdesign
      I'm working on a news feed that will show the most recent news in a full teaser grid, and all older news as a simpler archive-type list view. My selectors so far:
      $news_full = $page->children("template=news, limit={$page->feed_count_full}"); $news_archive = $page->children("template=news, start={$page->feed_count_full}, limit=9999"); The $page->feed_count_full field controls how many items to show in the teaser grid (I've confirmed it contains the correct value, and the $news_full selector works as intended).
      This works, but I don't like the limit in the second selector. Unfortunately, if I leave it out (i.e. I only specify a start, not a limit), the start is ignored and I get all news instead. Not a big problem as we will never have more than 9999 news, but it still bothers me, as semantically speaking I don't want to set a limit in this case.
      Is this the intended behaviour of start/limit selectors? Is there a cleaner way to specify an offset (start selector) without a limit?
      ProcessWire Version 3.0.123
    • By pwFoo
      I played with the Selectors object and would like to use it for a special use case...
      That is a custom Selectors object with dummy data converted to an php array to see the structure (Selectors object is a WireArray with "fields" added)
      Array ( [0] => Array ( [0] => Array ( [field] => seg1 [value] => val1 [not] => [group] => [quote] => [forceMatch] => ) [1] => Array ( [field] => seg2 [value] => val2 [not] => [group] => [quote] => [forceMatch] => ) ) )  
      But instead of "seg1" the field name is "field" with value "seg1" (= my field name).
      So I can't search the Selectors WireArray (= custom WireArray with added Selectors objects) with PW "find('seg1=val1')", Is there a way to search with "find()" or build a simple wrapper to make the elements searchable / filterable with find()?
  • Create New...