Jump to content

Getting Select Repeaters


Macrura
 Share

Recommended Posts

Hi  -

I'm having trouble getting all the repeaters on a page that do not have a checkbox selected;

that checkbox is meant to disable the repeater; so in this case if the checkbox is checked, has a value of 1, then it should not be shown;

for some reason i can't get this to work, i've tried many things, but i guess i still don't know the tricks for getting repeaters to work...

here are some of the things i tried:

The repeater is called 'slides' and the checkbox field is called 'disable_slide'

$slides = $pages->find("template=repeater_slides, disable_slide=0");

$slides = $pages->find("template=repeater_slides, disable_slide!=1, include=hidden");

$slides = $pages->find("template=repeater_slides, disable_slide=");

TIA for any advice/tips on dealing with repeaters!

Link to comment
Share on other sites

The repeater is called 'slides' and the checkbox field is called 'disable_slide'

$slides = $pages->find("template=repeater_slides, disable_slide=0");

This works for me just fine as follows:

$test = $pages->find("template=basic-page, disabler=0")
//$test is just a variable I create; disable is the name of the checkbox; basic-page is the template that has pages that have repeaters.

I then traverse the repeaters...

As for tips...repeaters are just pages under the page Admin. The repeater field itself (e.g. slides) is a page (whose parent is  called "Repeaters") and the repeater instances on each page are its grandchild pages :). The repeater's children are pages which have the repeaters. But you probably knew this already ;)

Repeaters

slides (the repeater field itself)

page 1 with repeater

repeater instance 1

repeater instance 2

page 2 with repeater

repeater instance 1

repeater instance 2

repeater instance 3

Link to comment
Share on other sites

Re-reading your post...I'm not sure I got your correctly...

Are the checkboxes within the repeater field or are they an independent field on a page that has several repeaters? i.e., do you want to disable the page (including all its repeaters) or do you want to disable individual repeaters on a page? (e.g. show repeater instance 1, 3 and 4 of page x but disable repeater instance 2 and 5 of page x).

Link to comment
Share on other sites

OK, did some more tests with the checkbox as part of the repeater...
 
slide = the repeater
disabler = a checkbox inside the repeater
 

foreach ($page->slide as $show) { 
	
	if ($show->disabler!==1) { //edited to ==
	      echo "<li>$show->title</li>";
	}

       else {
             echo "<li>I am hidden!</li>";
       }
}

//!==1 works; !==0 works; ==0 works; ==1 works

Edit:

I had used assignment (=) operator rather than comparison (==)operator. See correction in post below by Nik

Edited by kongondo
Link to comment
Share on other sites

OK, did some more tests with the checkbox as part of the repeater...

slide = the repeater

disabler = a checkbox inside the repeater

foreach ($page->slide as $show) { 
	
	if ($show->disabler!=1) { 
	      echo "<li>$show->title</li>";
	}

       else {
             echo "<li>I am hidden!</li>";
       }
}

//!=1 works; !=0 works; =0 does not work correctly (echoes "I am hidden in all cases"); =1 does not work (shows titles in all cases).
Are the above "not working" cases intended behaviour? I recall having read something about such selectors but can't seem to find it now..

There are no selectors in your example, right? Just objects with properties and plain PHP. And the problem lies within the operators you're using (if you've tried literally those): "=0" and "=1" are assignments not comparisons and the results are what I'd expect them to be. :)

Should be "==0" and "==1" naturally.

  • Like 1
Link to comment
Share on other sites

This works as with your example, there's nothing wrong with it except that you need to add include=all:

search and return all repeaters "slides" pages (internally have template "repeater_slides") with disable_slide not checked

$slides = $pages->find("template=repeater_slides, disable_slide=0, include=all");

And it returns a PageArray

So you can loop them out or whatever.

foreach($slides as $slide) echo $slide->title;


If you want to only get the repeaters from the page you're on this is almost same:

$slides = $page->slides->find("disable_slide=0");
  • Like 2
Link to comment
Share on other sites

@Soma,

Should something like this not work?

$slides = $pages->find("slides.disable_slide=0");// slides = repeater

Currently not working for me...(returning incorrect results)

Sorry, ignore: works fine... :). It finds all pages with the repeater "slides" whose repeater fileds "disable_slide" are not checked.

Link to comment
Share on other sites

@Macrura,

Sorry to hijack your thread :). I am also trying to further understand how I can use the API to access repeaters (and hopefully assist fellow newbies ;)). So, I will post the following code for the gurus to comment on please, thanks!

$r = $pages->find("template=basic-page, slides.count>0");// find pages with at least 1 slides (repeater)
foreach ($r as $p) {
	$v = $p->slides;
	foreach ($v as $b) {
		if ($b->disable_slide==0) {//checkbox "disable_slide" not checked
			echo "<p>$b->title</p>";
		}
	}
}

This works for me. The first selector find will grab all pages that have at least 1 "slides" (which is the name of the repeater). The pages found have multiple instances of the repeater "slides" -  meaning arrays within arrays, hence, nested foreachs which I traverse...For each result, I check that the checkbox "disable_slide" is not checked and only output those repeaters..

@Others

Dear gurus...is there a shorter way (other than nesting the first selector find  inside the first foreach) or more efficient way of achieving the same thing or this will do? Thanks.

Edited for clarity (See Soma's post below about "selector" :). Also see his more efficient code)

Edited by kongondo
  • Like 1
Link to comment
Share on other sites

The term "selector" is the string you define to search, like in CSS or jQuery .someclass{} or $('.someclass') and not the result or the method "find()". I've read in some threads and now here (kongondo) (other than nesting the first selector inside the first foreach) and it can be confusing.

Ok, find is your friend! :) Approaching it this way, with finding all pages with the repeaters, then loop all is all correct and required in this case, but seems like not so efficient to loop all repeaters just to find the not checked ones? Why not just use the wonderful search functions to get the repeaters not checked and then loop them?

$pa = $pages->find("template=basic-page, slides.count>0");
foreach ($pa as $p) {
    foreach($p->slides->find('disable_slides=0') as $r) {
        echo "<p>$r->title</p>";
    }
}
  • Like 3
Link to comment
Share on other sites

Maybe the example just isn't a very good one, as you don't know ahead if the repeater have any unchecked checkbox.

$pa = $pages->find("template=basic-page, slides.count>0, slides.disable_slides=0");
foreach ($pa as $p) {
    foreach($p->slides->find('disable_slides=0') as $r) {
        echo "<p>$r->title</p>";
    }
}

Should also work, not to loop pages that have no repeater that meet the criteria for nothing.

  • Like 2
Link to comment
Share on other sites

Maybe the example just isn't a very good one, as you don't know ahead if the repeater have any unchecked checkbox.

$pa = $pages->find("template=basic-page, slides.count>0, slides.disable_slides=0");
foreach ($pa as $p) {
    foreach($p->slides->find('disable_slides=0') as $r) {
        echo "<p>$r->title</p>";
    }
}

Should also work, not to loop pages that have no repeater that meet the criteria for nothing.

Edit: Didn't read code properly..of course Soma's code works! :). I had similar code earlier i.e., checking for checkbox state in the first find() but was not checking again in the inner foreach (as per my code above). Hence, I was getting and outputting results if at least one repeater on the page was unchecked even if others were checked. 

  • Like 1
Link to comment
Share on other sites

Apologies. Of course it works! This is Soma's code! I had a typo in my code. I'll go away and hide in shame until later... :-[ 

The typo: In the second foreach, I had ('slides.disable_slides=0') instead of ('disable_slides=0')

OK, now am really confused!!

Soma, doing it your way doesn't work :(


 

Maybe the example just isn't a very good one, as you don't know ahead if the repeater have any unchecked checkbox.

$pa = $pages->find("template=basic-page, slides.count>0, slides.disable_slides=0");
foreach ($pa as $p) {
    foreach($p->slides->find('disable_slides=0') as $r) {
        echo "<p>$r->title</p>";
    }
}

Should also work, not to loop pages that have no repeater that meet the criteria for nothing.

OK, now am really confused!! Soma, doing it your way doesn't work  :(. I tested with my way first (as shown above and it worked). But using your way, it returns results where there are at least one checkbox unselected and outputs both unchecked and checked checkboxes...I think I know why...let me think a bit..

Edit:

I think your last code doesn't work because of what I said in the post above. The first find will grab all pages that have at least one repeater checkbox that is unchecked irrespective of whether those pages have other repeaters with selected checkboxes. Remember though, it grabs the pages themselves but does not distinguish the repeater fields yet. Why the selected checkboxes are not eliminated in the second foreach I do not know though... :huh:

Edited by kongondo
Link to comment
Share on other sites

Lol kongondo, of course it works! :P Don't worry it happend a lot for myself. Since then I just try to double check and test throughout first before posting ;) and you'll get better at time goes on. 

  • Like 2
Link to comment
Share on other sites

Hi all - thanks for the posts - this definitely works - thanks Soma... don't know why i was blocking on this, must have been in a fog yesterday...

$slides = $page->slides->find("disable_slide=0");
Link to comment
Share on other sites

  • 4 months later...
$pa = $pages->find("template=property, calendar.checkin_1=16.11.2013, fireplace=1");
foreach ($pa as $p) {

    foreach($p->calendar->find('booked=0') as $r) {
        $r = $r->getForPage();
        $content .= renderItem($r);
    }

}

Hi,

I try to use this code to find free week for bookings. (calendar is repeater with dates and checkbox "booked")

1) Find all property with 16.11.2013 in calendar (by repeater).

2) Check that this week is free (checkbox "booked" = 0).

But in some reason, I just get property for this dates and checkbox don't work.

What I'm doing wrong? 

Link to comment
Share on other sites

Ryan, thanks for your assistant, but it was my fault. I using date field without strtotime.

But, I have some really strange bug.

I use "limit" in selector and it works not very well.

For example, if I use limit=1 or 2 or 3, I get the same numbers of result.

But, if limit=4 or 5, result = 3 item.

If limit=6,7,8,9 result = 4 item. 

Any idea why this happens?
 

For sure, this bug happens only for dates. $result = wire('pages')->find($selector); return normal results with right limits.

Here is my code:
	$selector = "template=chalet, limit=10";

	$result = wire('pages')->find($selector); 
	
	if (wire('sanitizer')->name(wire('input')->get->dates)) {
	
	  $dates = wire('sanitizer')->name(wire('input')->get->dates);
	  $dates = strtotime($dates);
	  
          foreach ($result as $res) {
	    foreach ($res->clndr->find('arrival=' . $dates . ', book=0') as $r) {
	    	$i++;
	    	if($i==1) {$result=$result->makeNew();}
	        $r = $r->GetForPage();
	        $result->add($r);
	        }
	  }
       }

return $result;

For example:

foreach ($res->clndr->find('arrival=' . $dates . ', book=0') as $r) 

 
if limit=8, $r= 7416,7889,7893,7898, (4 results)
if limit=10, $r= 7416,7889,7893,7898,7903, (5 results)
if limit=100, $r= 7416,7889,7893,7898,7903,7394,7402,7398,7817, (all 9 results)
 
Sorry for this dummy question. 
 
Maybe someone can help, what to do with foreach ($res->clndr->find('arrival=' . $dates . ', book=0') as $r) pagination?
Link to comment
Share on other sites

Well PW uses strtotime automatically when you provide it non-numeric values for any date field in a selector. For some reason it didn't understand that your text was intended to be a date. But glad you found a solution, converting it to a timestamp on your own. But just wanted to mention it's usually fine to supply a formatted date in a selector, so long as it's one that strtotime() recognizes. 

Maybe someone can help, what to do with foreach ($res->clndr->find('arrival=' . $dates . ', book=0') as $r) pagination?

Pagination is there to place limits on how  much data you pull from the database at once. As a result, it's not something you'd typically use with results of a find() that are already in memory. I'm not clear if your $res->clndr->find() there is being called on a Page object or a PageArray object. Is 'clndr' a Page or a PageArray? If it's a Page object, then you should be able to just supply a "limit=n" and it'll take care of the pagination for you (so long as you've enabled page number support in your template settings > URLs tab). If it's a PageArray (i.e. 'clndr' is a multi page reference field) then you can still use the "limit=n" in your selector, but you'll also want to supply a "start=n" in your selector as well, i.e. 

$limit = 10;
$start = ($input->pageNum - 1) * $limit; 

$items = $res->clndr->find("arrival=$dates, book=0, start=$start, $limit=$limit");

foreach($items as $item) { ... }
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...