Jump to content

Problem: Repeaters, "why u no save?"


Recommended Posts

Hey guys,

I am confused: my repeater fields are not saved from the API.

Here's the setup:

1. A repeater (named 'faqQA') which contains 2 fields: 'title' and 'body'.

2. A template containing the above repeater.

3. A page that uses that template and has one instance of the repeater.

Everything was created in the admin back-end. Repeater values were filled with sample text.

(The repeater is supposed to be a FAQ item collection).

This is the code I have in my template:

    $cFaqPage = $page;

    $faq = $cFaqPage->faqQA;
    $cFaqPage->faqQA->get(0)->title = '1';
    $cFaqPage->faqQA->get(0)->body = '1';
    echo $cFaqPage->faqQA->get(0)->title; // outputs "1"
    echo $cFaqPage->faqQA->get(0)->body; // outputs "1"


The script is supposed to update the values of the repeater fields with some new values, and to exit.

However, when I run it and go the the admin back-end to check the page, I still see the old values in the repeater fields.

This is quite sad, and I stripped my code down to basics and it's still not working.

Any ideas where to look at?

Thanks for your support in advance.

Link to comment
Share on other sites

Hi Valery,

See this page about  using the API to add or remove repeater items

Unlike other pages in ProcessWire, new repeater items must be created by ProcessWire rather than you. As a result, a helper method is provided called getNew(). You may call getNew() on any repeater field to get a new item. The item that it returns is ready to populate and has already been added to the repeater. Once populated, you simply save the page that the repeater field is on. 

There is a sample code on that page. As you can see, it can really be more simple compared to your code :)

  • Like 1
Link to comment
Share on other sites

.. and in case that you actually want to alter values of previously created repeaters, not just create new ones, seems that this related thread holds an answer for you. You'll have to save the repeater items individually, not just page that contains them. Try something like this instead:

$faqQA = $page->faqQA->get(0);
$faqQA->title = '1';
$faqQA->body = '1';

Completely untested and not something I've ever done, but looks like it should work (and kind of makes sense since repeaters are, under the hood, actually pages.)

Edit: fixed broken example. Probably :)

Edited by teppo
  • Like 2
Link to comment
Share on other sites

teppo, thanks a ton! Now, looking at repeaters as pages makes a lot more sense to me now.

I won't put my updated code here since it repeats renobird's code from the thread. You have to iterate through the repeaters and treat them one by one as if they were normal pages.

Which is, as you correctly state, exactly what they are. I can even see them when browsing down the Admin page in the back-end.

However, I must say that $page->repeater->get(0)->of(false)->save(0) does not work.

Thanks again!

Link to comment
Share on other sites

I tried the following:

$page->repeater->get(0)->title = "BLAH!";

This only gave me the usual

Error:     Exception: Can't save page... Call $page->setOutputFormatting(false)... 

So, for now I think I'll better stick to the proposed solution.

Link to comment
Share on other sites

An obvious note but I'll make it nevertheless: no necessity to of(false) the page containing the repeater field.

Just of(false) and save the repeater field-page itself and you're done.

Link to comment
Share on other sites

Hey Ryan,

I checked just now and the following code successfully sets the 'title' field of my repeater 'faq' to "WORKS!"

    $page->faq->get(0)->title = "WORKS!";

Can I kindly ask you to share your opinion on what the right way to set repeater values through the API is?

Link to comment
Share on other sites

Can I kindly ask you to share your opinion on what the right way to set repeater values through the API is?

That syntax is valid–I think when I replied before that the morning coffee hadn't quite kicked in yet. :) But, if you need to access the first element, I think it's better to use first() rather than get(0) just because there's always a possibility that the item at index 0 was removed somewhere else, or that the PageArray was at some point sorted so that index 0 was no longer the first item. If you don't have any other manipulations going on with your PageArray, then accessing get(0) is probably just fine though. 

  • Like 1
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

  • Create New...