Jump to content

Repeater Fields How To


aw.be
 Share

Recommended Posts

Hello.

First off, I'm a beginner with php (so you understand where I'm coming from) but I've been learning lots through the forum and am trying to learn more from a book.

I have set up some repeater fields for a 'construction projects' page. I've got everything up to the point to adding php to the page template. The issue is that my repeater fields have static html in them as well. This is the way it's set up:

h3 - project name

(client enters name here)

h3 - project budget

(client to enter info here)

h3 - project description

(client enters info here)

client uploads photo.

That's the best way I can explain it. I understand how to use the example code snippet from the repeater field tutorial but am not sure how to go about integrating it as I described above.

I don't expect to be spoon fed the solution, but if someone could point me in the right direction I know enough that I can probably muddle my way through it - I learn best that way anyway.

Thanks for the help.

Aaron

Link to comment
Share on other sites

You should think if repeaters are the best way of achieving what you want. In this case, I suspect that it would be better to create each project as a child of a "projects" page. But I will answer your doubt anyway.

Its not much different then doing the same with other kinds of fields. But, like with images, the field return a page array that you have to iterate with a foreach()

Taking the example on the repeater fields docs http://processwire.c...ypes/repeaters/ (is this one that you were talking about?)

foreach($page->buildings as $building) {
  echo "<h2>{$building->title}</h2><p>";
  echo "Height: {$building->feet_high} feet, ";
  echo "Floors: {$building->num_floors}, ";
  echo "Year built: {$building->year_built} </p>";
} 

Notice that it's not that different from your example, and all the html is being echoed from inside the foreach.

The same example can be also written with this alternative sintax, if it makes it more clear for you:

<? foreach($page->buildings as $building):?>

  <h2><?=$building->title ?></h2>

  <p>
  Height: <?=$building->feet_high ?> feet,
  Floors: <?=$building->num_floors ?>,
  Year built: <?=$building->year_built ?>
  </p>

<? endforeach; ?>

You just have to adapt it to your html code. In your case I can imagine something like this:

<? foreach($page->projects as $project): ?>

  <h3>project name</h3>
  <p><?=$project->name ?></p>

  <h3>project budget</h3>
  <p><?=$project->budjet ?></p>

  <h3>project description</h3>
  <p><?=$project->description ?></p>

<? endforeach; ?>
  • Like 2
Link to comment
Share on other sites

Diogo, thanks for your answer.

Just so I do this the best way, I'm trying to figure out how to do this using your suggestion of child pages. Is Ryan's solution in this thread what you're talking about?

With my limited knowledge, I think I can create a new template for the fields I want to be repeatable, but I'm not sure what code to use in my 'projects' template to allow repeatable instances of my new template.

Does that make sense?

Aaron

Link to comment
Share on other sites

With my limited knowledge, I think I can create a new template for the fields I want to be repeatable

You would create a new field using type 'Repeater', not a template. Though technically you are correct in that a repeater field does create a template to group them, behind-the-scenes. But this is not something you usually need to think about when dealing with repeater fields.

  • Like 1
Link to comment
Share on other sites

My suggestion was simply to create a "projects" page, and have all the projects as it's children:

-projects (template "projects")

--projectA (template "project")

--projectB (template "project")

--projectC (template "project")

Template "projects" doesn't need any field, or even a template file associated. It exists only for holding the children.

(in the "family tab" of template editing, choose "project" as the only allowed template for children)

Template "project" has the fields "title", "budget" and "description". Doesn't need a template file if you don't want them to have their own URL.

(in the "family tab" check "no" for "can this template be used for new pages?")

On your "construction projects" page template do something very similar to the above:

<? foreach($pages->get("/projects/")->children as $project): ?>

  <h3>project name</h3>
  <p><?=$project->title ?></p>

  <h3>project budget</h3>
  <p><?=$project->budjet ?></p>

  <h3>project description</h3>
  <p><?=$project->description ?></p>

<? endforeach; ?>

The editor just have to create a new page under "projects" for each project.

This is the most common way of doing this kind of thing on PW.

  • Like 2
Link to comment
Share on other sites

I finished these. I ended up using the repeaters as what I wanted seemed very close to the example Ryan used in the videos.

Diogo - Because I'm new to all this (php and dynamic sites) I'm only half understanding what you're explaining to me. I think that as I go through more of the documentation and other forum posts I'll get it. Thank you.

Aaron

Link to comment
Share on other sites

  • 3 weeks later...

If I understand you correctly, you can get the first item using this:

$page->repeater_field->first()

A repeater field is returned as a PageArray.

This way it also gives an error message, but i probably wasnt realy clear with my explination

Lets say i have a field named 'thingy' with field type repeater.

I use the following code to print it to the page:

foreach($page->thingy AS $data) {
   echo $data->render();
}

then in the templates folder i use the file with the name 'repeater_thingy.php'

in that i have something like this:

$out = '';
$out .= "<div class='item'>";
$out .= "<h2>{$page->headline}</h2>";
$out .= "</div>";
echo $out;

I need to know in the 'repeater_thingy.php' file what the item nunber is or even better if it is the first item.

Link to comment
Share on other sites

I don't know if you can do this with render(). are you using the repeater_thingy.php for anything else? you can just turn it in an include, or put the code directly inside the foreach, and like this the check should already work.

Link to comment
Share on other sites

I found a way to check within a repeater template files if the repeater item is the first or the last

if ( empty($page->prev-id) ) // first item

if ( empty($page->next-id) ) // last item

This gives the information that is needed, its a little work around but it works fine :)

  • Like 2
Link to comment
Share on other sites

This is another way to accomplish it, perhaps more efficiently:

$n = 0; 
$total = count($page->thingy); 

foreach($page->thingy as $data) {
 $n++;
 $data->isFirst = ($n === 1);
 $data->isLast = ($n === $total); 
 echo $data->render();
}

Your repeater_thingy.php template should now be able to compare against $page->isFirst and $page->isLast

  • Like 3
Link to comment
Share on other sites

  • 6 months later...

Something I can't get my head around, is how to modify existing repeaters via the API.

I can get them output to a form, but I can't figure out how to save the changes (if there are any).

In this case, I'm just using text fields.

Link to comment
Share on other sites

@renobird - funny, a few hrs ago i was trying to get my head around how to import CSV data into repeaters... not sure if it is relevant to your question, but it is something i might need to do soon (importing users where phone and email are repeatable)

Link to comment
Share on other sites

Thanks Soma, 

Very much appreciated. I was getting too wrapped up in trying to update the existing repeaters.

You're method of removing and recreating makes things a lot simpler. 

I see a flatter.com account in my future. ;)

Link to comment
Share on other sites

  • 5 years later...

Hi everyone,

I have a repeater inside a repeater (two nested levels).

These repeaters are populated via the api.

  $page->of(false);
  for ($x = 0; $x <= 10; $x++) {
    // first level repeater item
    $repeaterItem = $page->repeater->getNew();
    for ($y = 0; $y <= 10; $y++) {
      // second level repeater item
      $nestedRepeaterItem = $repeaterItem->nestedRepeater->getNew();
      // edit item
      $nestedRepeaterItem->someField = "some datas";
      // save item
      $repeaterItem->save();
      // $nestedRepeaterItem->save();
      // $repeaterItem->nestedRepeater->add($nestedRepeaterItem);
    }
    // save item
    $repeaterItem->save();
    // $page->repeater->add($repeaterItem);
  }
  // save page
  $version->save();

To obtain the expected result, I oddly had to use this command (twice) :

$repeaterItem->save();

Commented lines are what I thought would be right, but if I do I end up with several times the same repeater items.

@Soma your example suggest:

...

$item->save();
        
// add the repeater item to the page
$mypage->teasers->add($item);

...

But it didn't work in the nested situation above, any idea why ?

The only answer I see is that ->getNew() takes care of adding the item inside the repeater (maybe a recent addition to the api).

Cheers

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

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...