Jump to content

Repeatable Fields


ryan

Recommended Posts

So, all your quotes are in one page, inside a repeatable field? sorry, because I still didn't get this.

edit: in your code you never call the field "employee_quotes", to have access to "employee_quote", you should call it like this on the selector

("employee_quotes.employee_quote != ''")

edit2:

I know what is happening. because you are calling the fields inside of the repeater directly, and because these fields are inside the special repeater hidden pages, those are the ones that PW is finding on your first line. That's why you have results only when you are logged in as superuser. Give us some more details about what exactly you want to do. You have more than one page with the repeater "employee_quotes"?

Anyway, in general this should work for what you want:

$quoteList = $pages->find("employee_quotes.employee_quote!=")->shuffle();
$quoteList = $quoteList->shift();
$employeeQuote = $quoteList->employee_quotes->shuffle();
$employeeQuote = $employeeQuote->shift();
if ($employeeQuote) {
 echo "<blockquote>{$employeeQuote->employee_quote}</blockquote>";
}

But would be less complex if all repeaters are in one page only

Link to comment
Share on other sites

@Soma, thanks for your thougts. My first assumption was that the repeater itself works fine on the page where it is called. Only on the homepage I didn't get any output IF I was logged out.

@diogo, also thanks for your thoughts! What I am trying to accomplish is to get one random quote from all employees on the homepage.The repeater field itself and the textfield is only used on one template and on 4 pages (4 employees). Like I said to @Soma on the page itself it works fine pulling random quotes.

Your

$pages->find("employee_quotes.employee_quote!=");

won't give any results. It doesn't make a difference if I am logged or not. I also tried to get a list of employees and loop through all of them, but that seems like a bit overkill. I understand now that fields within the repeater are hidden pages. That does make a lot of sense. The question is: how to work my way around it?

Link to comment
Share on other sites

Arjen, I can't seen to duplicate this. Here's the selector I'm using:

echo $pages->find("buildings.building_name!=''); 

Check that you are running the latest ProcessWire, version 2.2.2. Make sure that your page(s) with the employee quotes are not unpublished or hidden. Double check that you've got all the field names spelled right and in the same case, between the field definition and your selector (we all make this mistake on occasion, so just double check).

Link to comment
Share on other sites

Your

$pages->find("employee_quotes.employee_quote!=");

won't give any results

can you put this on your template to make sure it doesn't?

echo $pages->find("employee_quotes.employee_quote!=");

it should echo a list of page IDs

this works for me

echo $pages->find("repeat.email!=");
Link to comment
Share on other sites

@ryan, latest ProcessWire (check), not unpublished or hidden (check). Double check that you've got all the field names spelled right and in the same case, between the field definition and your selector (we all make this mistake on occasion, so just double check) (check).

I did work it out, but the other way around. I thought $pages->find("repeater_name.field_name") would find the fields within the repeater itself. I just pulled the person I want the quotes from and then shuffled the list, grab the first and output the quote. My idea was to get all the quotes and shuffle then shift, but the client and I decided his quotes were fine too. I guess this might have to do with my thinking. Still learning everyday that PW is so simple in it's ways and my previous CMS experiences/thinking is way to complicated. Thanks guys for the help.

Here is the code I finally used.

$johnsonPage = $pages->find("template=employee, title~=Johnson")->first();
$quoteList = $johnsonPage->employee_quotes->shuffle();
$quoteList = $quoteList->shift();
$employeeQuote = $quoteList->employee_quote;

EDIT: @diogo, I was thinking... This code actually grabs the pages the quotes are associated with right? Or does this code grabs the quotes itself?

Link to comment
Share on other sites

EDIT: @diogo, I was thinking... This code actually grabs the pages the quotes are associated with right? Or does this code grabs the quotes itself?


// this returns the first page with Johnson included in the title (I'm not sure why you do it like this, why don't you just $pages->get("name = johnson") it?
$johnsonPage = $pages->find("template=employee, title~=Johnson")->first();

// this returns an array with all the elements (the quotes) of the repeater field "employee_quotes" inside the page and shuffles it's order
$quoteList = $johnsonPage->employee_quotes->shuffle();

// this removes the first element from the array, and returns it
$quoteList = $quoteList->shift();

// this returns the content of the field "employee_quote" that is inside of that element
$employeeQuote = $quoteList->employee_quote;

in resume, the code grabs a random quote from the employee named Johnson.

Link to comment
Share on other sites

Thanks for your insights!

Actually I was referring to your code. My apologies if I didn't make myself clear.

echo $pages->find("repeat.email!=");

Does this code grabs the pages on which the quotes are associated ? Or does this code grabs the quotes itself (across multiple pages)?

Link to comment
Share on other sites

you mean an array with all the quotes? Not with a PW method, i think... you would have to loop through all the pages and through the repeater in each page, and then join the arrays.

$allQuotes = array();
foreach($pages->find("employee_quotes.employee_quote!=") as $p){
$theseQuotes = $p->employee_quotes;
$allQuotes = array_merge($allQuotes, $theseQuotes);
}

This should work. (it doesn't)

edit:

to echo all the quotes:

foreach($allQuotes as $q) {
echo "<blockquote>{$q->employee_quote}</blockquote>";
}

edit2: wait, this doesn't work :(

edit3: This does work:

$allQuotes = new PageArray() // thanks to soma for this 
foreach($pages->find("employee_quotes.employee_quote!=") as $p){
$theseQuotes = $p->employee_quotes;
$allQuotes = $allQuotes->import($theseQuotes);
}

foreach($allQuotes as $q) {
echo "<blockquote>{$q->employee_quote}</blockquote>";
}
  • Like 1
Link to comment
Share on other sites

Sure you can

// get all pages that have at least 1 quote
$res = $pages->find("employee_quotes.count>0");

// add all quotes to an PageArray
$allquotes = new PageArray();
foreach($res as $r) $allquotes->add($r->employee_quotes);

// shuffle or whatever you please
$allquotes->shuffle();

// output all
foreach($allquotes as $q){
echo "<p>$q->employee_quote</p>";
}

  • Like 2
Link to comment
Share on other sites

@soma, @diogo,

This is what I've been looking for. Thanks you very much! *double like this* So in retrospect it was my way of thinking. I thought that with the $pages->find you can also find the fields. Now I see it doesn't make sense at all the way I was thinking. I dig deeper into PW with PageArray().

Thanks all for your thoughts!

Link to comment
Share on other sites

  • 3 weeks later...

This is interesting. I have been using the repeatable field for a little while and it's a huge benefit. I'm stuck though.

I have several pages with a repeater field and I want to display the fields, organized by page:

<h2>Page Title</h2>
   <ul>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
  </ul>
<h2>Page Title</h2>
   <ul>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
  </ul>
<h2>Page Title</h2>
   <ul>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
    <li>repeatable field info</li>
  </ul>

Like so. The array that Soma and diogo wrote seems like the ticket but does that just return the contents of the array as one big list or can it be organized by page? I have no idea how you'd do that.

Link to comment
Share on other sites

digitex, look at the markup and you see a somewhat 2 dimensional list. That's always done using nested foreachs.

foreach( $pages->get("/someparent/")->children() as $pa ) {
 // $pa is the page
 echo "<h2>$pa->title</h2>";
 echo "<ul>";
 // cycle the repeater field as if they are pages (they are)
 foreach( $pa->repeaterfield as $rp ) {
echo "<li>$rp->info</li>";
 }
 echo "</ul>";
}
  • Like 2
Link to comment
Share on other sites

THANK YOU SOMA!

I thought it must be easier than I was making it and that something was just a little off on what I was doing. I had pretty much what you have (you showed me a few ways to simplify things) but it wasn't working. With your example to go by as correct, I figured there was something else wrong so I looked at my selector and found my problem.

Now all I need to do is glue the hair I pulled out trying to get this, back on my head. Thanks again.

Link to comment
Share on other sites

You're welcome. Haha, don't hurt yourself please! ;)

Just for throwing in when using php "Wire"-tag ( ;) ) short notation the above could also be something like this.

<? foreach( $pages->get("/about/")->children() as $pa ) : ?>

<h2><?= $pa->title ?></h2>
<? if( count( $pa->teasers ) ): ?>
	<ul>
	<? foreach( $pa->teasers as $rp ) : ?>
		<li><?= $rp->element_title ?></li>
	<? endforeach ?>
	</ul>
<? else: ?>
	<p>No entries found</p>
<? endif ?>

<? endforeach ?>

(short tags needs to be enabled on server, but only few hostings have it disabled. In near future it will always be enabled in php5.4)

  • Like 4
Link to comment
Share on other sites

  • 3 weeks later...

How does it fails? Does firebug or chrome console give you any error messages?

Also: are you sure you really need repeater inside a repeater? Of course depends on your use case - it very well might be the best possible solution here.

Link to comment
Share on other sites

How does it fails? Does firebug or chrome console give you any error messages?

Also: are you sure you really need repeater inside a repeater? Of course depends on your use case - it very well might be the best possible solution here.

Processwire returns this on upload

{"error":false,"message":"Page not saved (no changes)"}

I could end with subpages with repeaters on each of them but page structure is more logical if there would be possibility to use nested repeaters on it

Link to comment
Share on other sites

Iam using in one project Repeatable Fields inside another Repeatable Fields. Everything works find except image uploads in inner Repeatable Field.

Unfortunately I don't think that file fields can be nested beyond one level of repeaters. There is some necessary security going on behind the scenes that limits the scope of how deep an ajax request can go, and I think that's what you are running into here. The truth is that you may actually be able to get it to work if it weren't using ajax uploads (like if you were using Safari, which doesn't support ajax uploads). But I think you may be better off avoiding nested repeaters if possible. Nested repeaters are a rather complex thing to develop around and may be difficult to maintain vs. a simpler solution that doesn't rely on nesting. Still, you've got me curious and I do plan on experimenting here and trying to duplicate the next time I'm working with repeaters, just to be certain I'm right about the reason it's not working. If there is an easy way around it, I'll find it. Nested repeaters do sound fun. :) But either way, for practical purposes, I don't think it's good to build around a structure that requires nesting repeaters.

Link to comment
Share on other sites

Hi,

It seems I found another bug with repeaters (unless it was already reported, though I didn't find about it in his thread)...

Here is what I did:

- I created one repeater field named "sliders" containing 3 fields title, body and images

- I added the field sliders to my home template

- I added 3 elements of type sliders on my homepage (which uses the home template), filling each with a title, a body and one image

- then I went back to the Fields manager and created a new repeater field named features by cloning the sliders field so features will have the same 3 fields title, body and images

(so far so good)

- went back to editing my homepage, and here the problem starts...

- first it already contained 3 elements of type features being a copy of my 3 previously created elements of type sliders (fine because I needed 3 elements anyway, "I'll just have to edit them" or so I thought)

- but then if I edit any field of, say, "Features #1" element, the change is also made to element "Sliders #1" !

- and I can't edit elements from sliders type anymore ! if I save a change in sliders, it is not applied; if I save a change in features, it is applied to features and sliders

Any idea ? Maybe I should not clone a repeater field ?

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
  • Recently Browsing   0 members

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