Jump to content

Repeaters within repeaters, and the pageFields inside them.


darrenc
 Share

Recommended Posts

I apologize in advance for the long post, but it is an easy read.
Technically repeaters can be nested (I've done it before, though disabled it), but it creates so much potential for problems that I didn't think we'd want to support that. Plus considerations for 3rd party Inputfield modules, and the list goes on. The situations where nested repeaters are worth the compromises is pretty rare, as there's usually a better way to accomplish the same thing. Ultimately decided we shouldn't have support for it at this time. But if you can describe what you are trying to accomplish with nested repeaters, I may be able to describe alternative ways to achieve the same thing. 
-Ryan Cramer
I'm dealing with a situation where I can't think of how to do this, practically, without using repeaters within repeaters. I'll try to be very clear but keep the example simple: a "vacation home rental" site. 
 
Let's say you're a user looking for somewhere to vacation in 2015, you go to the website and click the main menu item "All Homes (page)" and are met with a list of all the homes you can potentially rent. You pick any one of them and get to the page (child page of homes) where it displays for you the basic details - description, body, maximum occupancy, pets allowed,  etc... all plain fields on the "home" template object. 
 
Now, each home can be rented for different rates at different times of the year. Maybe it is at a popular summer spot so the rates are more expensive during the summer, or very popular in winter due to it's proximity to a ski mountain. You probably make a repeater called "rental_period" with start/end date fields on it among other things. However inside each of those rental_periods exists options for prices on a daily, weekly, scale. eg:
 
  • /all-homes/malibu-darrens-beach-house/
    • rental_period #1 - Summer
      • rate_option #1 - Daily: $200
      • rate_option #2 - Weekly: $600
    • rental_period #2 - Winter
      • rate_option #1 - Daily: $50
      • rate_option #2 - Weekly: $200
      • rate_option #3 - Monthly: $600
As a hypothetical owner I've decided that my beach house is so popular that I can maximize my income by not offering a monthly rate during the summer. In winter in order to entice longer stays I steeply discount a rate. Obviously this would vary home by home.
 
 
Question #1 -- How would you set this up differently if not using repeaters inside repeaters?
 
To me this only makes sense as a rental_period repeater with a rate_option repeater inside it. Neither of them is ever going to get particularly long - but maybe one house only has one rental_period, yet another has 5. Furthermore maybe one rental_period has a couple of rate_options, but another rental_period on a different property has several (weekday, weekend, holiday, three night minimum, weekly, etc). This type of setup seems unwieldy if considering setting these up as child and grandchild pages of each home, and I am not sophisticated enough to think of another way.
 
 
Question #2 -- Referencing page fields inside the repeater broke down. What am I doing wrong?
 
Given my example, lets say the price is a simple integer field "rate" but the daily|weekly|monthly is a select box page reference field named "time_period". I wasn't able to access properties of the time_period page as I expected to. In simplified code...
// example home.php which outputs property and rate details

// output the basic page-level stuff
echo $page->get("headline|title");
echo $page->location;
echo $page->description;
echo $page->occupancy;
// etc...

// output rental periods repeater
// only ignoring count() testing for purposes of simple example
foreach ($page->rental_periods as period){
    echo $period->name;
    echo $period->start_date;
    echo $period->end_date;

    // loop my repeater inside my repeater
    foreach ($period->rate_options as $option){
        // page reference, did not echo the time_period title as expected!
        echo $option->time_period->title; 
        echo $option->rate;
    }
}

In the code above, which I thought would be fairly straight forward, my "$option->time_period->title" echoed nothing instead of the title of the page.

If you've stick with me this far I want to thank you for entertaining my rambling. I am curious how you all would approach something like this, perhaps get some tips as to why this approach could have drawbacks, as well as maybe get some insight into why my output failed. 

Link to comment
Share on other sites

Question #2  is answered: i had my page field set up wrong and it was returning a page array instead of a page.

If anyone wants to discuss an alternate data structure to solve question #1 I would still be interested in hearing it. Thank you.

Link to comment
Share on other sites

You can create a detailed table of data using a repeat field for each of your "rows"

So create a repeater field that has the following fields:

1. Rental Period (season?)

2. Daily Rate

3. Weekly Rate

4. Mothly Rate

plus any other options.

Now, first of all, loop through them and sort them by rental period.

Having done that, loop through those results to display the other fields

You can do this ad-infinitum, really.

Somewhere on this forum someone helped me with an events list that had to do the same thing (though we had to split the date apart first)

First, it looped by year, then by month, then by event. The result was a Year heading, followed by the list of months (only those actually used) and under each month the list of events for the month.

Does that help you in the right direction?

Link to comment
Share on other sites

2. Daily Rate

3. Weekly Rate

4. Mothly Rate

Joss this is exactly where I decided that a repeater needed to exist because "daily, weekly, monthly" aren't the only possibilities. The most flexibility for the system would allow the owners to define periods as they see fit, so maybe someone new to the system might want a "weekend" rate, another a "holiday" rate, or even create some kind of "company employee nightly" rate. The potential for different rate types could go from the 3 standard into tens (but probably not hundreds) of rate types. In that case "rate_type" makes the most sense as a page reference rather than making more and more rate fields manually. 

Because of that I thought that the only way to handle allowing someone to dynamically choose (or create) their own rate type, I needed that second-level repeater.

Granted there maybe could be a better way to approach this while allowing the same flexibility for the end-user. But maybe not?

Link to comment
Share on other sites

Why not just have them enter the period and the rate type and the rate in the repeater. If you used page fields to store the period and rate types, they could add new ones as needed using the "Allow new pages to be created from field?" so they wouldn't have to retype them each time.

Do you think that would work at all?

Link to comment
Share on other sites

That's a good question adrian and something I had considered as a solution. 

  • jan1 - jan25
    • daily, $100
    • weekly, $300
  • jan26 - feb5
    • weekday, $150
    • weekend, $400

-vs-

  • jan1 - jan25, daily, $100
  • jan1 - jan25, weekly, $300
  • jan26 - feb5, weekday, $150
  • jan26 - feb5, weekend, $400

The first one with nested repeaters logically makes more sense to me, and requires less inputting of the duplicate data for the user (date range in this, simplified, example). Is there an advantage, or necessity, of flattening out the data like you suggest? I'm trying to determine where a structure like this could go horribly wrong.

Link to comment
Share on other sites

If you were doing this as a crud system without processwire involved, you would do this as two actions - create a rate type (whatever that consisted of) and then use that type.

So, do the same thing here.

Your rates can be pages which are created under a parent and then can be selected using a page select as part of the repeater.

What I am not sure about is how you can do that on an individual basis so that each user has their own selection.

Link to comment
Share on other sites

Another option I can see is to create the rental seasons as child pages of the house, and in each of those pages have a simple repeater field where you set the rate types and values.

If you're feeling up to it, you could even create your own fieldtype and inputfield combination for all of those - instead of using repeaters. Ryan put together a great example that could get you started - Events FieldType and InputField.

Link to comment
Share on other sites

  • 2 weeks later...

That's a good question adrian and something I had considered as a solution. 

-vs-

The first one with nested repeaters logically makes more sense to me, and requires less inputting of the duplicate files for the user (date range in this, simplified, example). Is there an advantage, or necessity, of flattening out the data like you suggest? I'm trying to determine where a structure like this could go horribly wrong.Well I see

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...