Jump to content

Checkbox Group for Field


Pete
 Share

Recommended Posts

Hi folks

I've been busycreating fields I have for a MODx site so that I can begin moving the site over to PW. For the most part this has been made straightforward by how simple PW is.

There's one field I'm having trouble working out how to do though - it's a checkbox group called Type where there are multiple checkboxes you can tick - see the highlighted field in the attached image.

Is it possible to have a checkbox group, or a multiple select list? I see there's the option for field groups, but this doesn't seem to be exactly the same - I think in the attached example MODx would save the selected text boxes as a comma separated list - arguably less useful than 3 separate fields (I'd argue that it is useful as you can use mySQL's IN() statement to see if a value is in a comma separated list in the database).

post-1356-132614278023_thumb.gif

Link to comment
Share on other sites

Pete, this is possible and will show you one of the most powerful features of processwire. Doing this first time feels little strange, but soon you will see how convenient and flexible this is.

You can achieve this with "Page" field. First you create page called "Type". This is just a container page and might be something you do not want to be accessible for public (maybe only for superadmins?). Sometimes you want to keep these under some other page, so url would be /tools/type/ or /settings/type/ etc.

Under that page you create all your selections as pages. Developer, Publisher and Current Rights Holder would all be pages under "Type" page. It works with any template, but I usually have one "referencepage" template for pages that contain only title field. You might also create template called "type" (you might wanna add more details for type, like small description or icon.. anything).

Now that you have your pages somewhere, it is time to create page field. Page field allows you to create one-to-many or many-to-many relationship between your pages. Add new field, and choose "Page" as a type. Then you just choose that "Parent of selectable page(s)" is your /type/ page (or /tools/type/ or wherever you put it). Alternatively you could choose "Template of selectable page(s)" if you have dedicated template for wanted selections.

And finally you can select "Input field type" where you find "Checkboxes" or "SelectMultiple". There is also asmSelect which is custom field that pw uses a lot internally. It also allows multiple selections.

This might seem like a lot of work or complicated, but once you do this and realize all the superpowers that it brings, you'll never look back ;)

PS: If you already knew this all and you were just looking for quicker alternative, then I'll keep my answer as a future reference.

  • Like 3
Link to comment
Share on other sites

Oh, I forget to write how you can use these selections in your templates. Let's assume that you gave your page field name "type". So this is how you get all pages that have checked "Developer" from them:

<?php
// We need to get "developer" page first
$developer = $pages->find("parent=/type/, name=developer");

// Next we find all pages that have type field with developer checked (we use $developer page from last line here):
$dev_pages = $pages->find("type=$developer");

// Let's loop pages and echo title and all types they have:
foreach($dev_pages as $p) {
 echo "<h2>$p->title</h2>";
 foreach ($p->type as $type) {
   echo "<p>$type->title</p>";
 }
}

or if you just want to check if current page has Publisher checked:

<?php
$publisher = $pages->find("parent=/type/, name=publisher");

if($page->type->has($publisher)) {
  echo "Publisher";
}

Link to comment
Share on other sites

Great explanation Antti!

Here's a couple more simple examples. I think that 'type' might be a reserved word (not positive), but I'll change it to 'atype' in the examples just in case. Iterate through the selected values on your $page:

foreach($page->atype as $a) {
    echo "<p>" . $a->title . "</p>";
}

The output might look like this:

<p>Publisher</p><p>Developer</p>

Or, if you made your page reference a single page reference, then it's just:

echo "<p>" . $page->atype->title . "</p>";

Antti's second example can also be simplified a bit to this:

if($page->atype->has("name=publisher")) {
    echo "Publisher"; 
}
  • Like 1
Link to comment
Share on other sites

"Type" is not reserved word, I tested before I posted (I thought that it is myself too) :)

Antti's second example can also be simplified a bit to this:

<?php
if($page->atype->has("name=publisher")) {
    echo "Publisher"; 
}

Thanks for this. I noticed that this is probably possible when I was checking API, but never used it that way - so I didn't dare to post it. Damn you have coded brilliant software Ryan!

  • Like 1
Link to comment
Share on other sites

Thanks guys. This will work fine, however it does seem rather overkill in situations calling for very small groups of fields like this.

This way there are 3 entries in the database instead of 1. I know it's not the end of the world and that the query will doubtless run just as fast, however it seems a little counterintuitive to have them as pages in the backend at all.

On the other hand, it makes the list easier to add to if required which would be good in a lot of cases, but less so in this case as it's a set list that will never change.

It just feels a bit weird is all :P;)

Link to comment
Share on other sites

I guess what I'd like to see is a variation on the Fieldtype Select module that allows multi-select or checkboxes when you set the field up: http://processwire.com/talk/index.php/topic,245.msg1426.html#msg1426

However I'd have no clue how to achieve this - I'll look into the Fieldtype Select module later tonight and see if I can modify it a bit :)

Link to comment
Share on other sites

Ooookay, now I've actually tried the examples posted above I love the way you guys have suggested to do it. Much quicker, if a little weird at first and more straightforward for lists that might have to be added to in future by non-programmers.

  • Like 1
Link to comment
Share on other sites

Thanks guys. This will work fine, however it does seem rather overkill in situations calling for very small groups of fields like this.

This way there are 3 entries in the database instead of 1. I know it's not the end of the world and that the query will doubtless run just as fast, however it seems a little counterintuitive to have them as pages in the backend at all.

Once you start really using them, you may not want to do it any other way. :) While the page reference type is infinitely scalable, I also think it's a good solution for small needs too.

Lets say that you needed to associate some other data with your Publisher, Developer and Current Rights Holder. For instance, maybe a brief summary of what they are, an graphic/image/icon, or anything else. You just add that field to your template used by those entries. I'll reuse a previous example:

<?php // for syntax highlighting
foreach($page->atype as $a) {
    echo "<p><a href='{$a->url}'>{$a->title}</a><br />{$a->summary}</p>";
}

Note how I liked to the atype page. This presents some cool new possibilities for usability (not to mention things for Google to index). We could make the atype page show all pages that have a given type selected. Depending on the context, this might be really useful to the users of your site (if not, yourself). Here's what we might do in the atype template:

<?php
echo "<h1>{$page->title}</h1>";
echo "<h2>{$page->summary}</h2>";
echo "<h3>Pages with {$page->title} selected:</h3>";
$entries = $pages->find("atype=$page, limit=25");
echo $entries->render();  

When you start building sites in this manner, the page references start to become valuable parts of the site's structure. You start to build connections that weren't possible before, many of which are genuinely useful. But for everything else, or for pages that may not have a place in your site structure, put them in a /tools/ or /config/ section of your site, which you may or may not make accessible to guests. Here are a couple examples:

http://www.tripsite.com/tools/difficulty/easy/

http://www.tripsite.com/tools/tour-types/self-guided/

From a technical standpoint, while you are right that there may be a max of 3 entries per page in the database instead of 1, each entry is an integer (a pointer to a page) rather than a string of text, like you see in many other CMS's select types. So perhaps there are 3 entries, but they are consuming far less storage resources than in the other CMS (or in fieldtype you linked to).

Lets say you decide the word "Current" in "Current Rights Holder" is not necessary and you want to change the label to "Rights Holder". In PW you just go and change it. In other CMSs, you might not be able to, or if you did, it might corrupt the data leaving all existing "Current Rights Holder" entries there while new ones are labeled "Rights Holder".

On the other hand, it makes the list easier to add to if required which would be good in a lot of cases, but less so in this case as it's a set list that will never change.

If you are certain you won't ever want/need to do anything more than just show a Developer, Publisher and Current Rights Holder checkbox, then there's still no harm in keeping it a Page reference. But if you don't want to take that route or one reason or another, you can make them single checkbox fields:

$page->developer

$page->publisher

$page->rights_holder

Wrap a fieldset around them to keep them together. I only use these checkboxes for single on/off toggles, but just wanted to mention this alternative if you don't want to use the Page fieldtype for one reason or another. But as a best practice, I nearly always recommend using Page references for this kind of stuff as I think it leads to good design structure, scalability and long term benefits. But I can say that only for my own sites, and I know everybody's needs are different.

Link to comment
Share on other sites

Funnily enough I was thinking of doing something just like what you mentioned in those examples - Publisher and Developer lists could be quite useful and another easy source of content for search engines to lap up as you say, but I'd probably filter out Current Rights Holder as it only makes sense in the context of a specific game.

I guess this would be easy enough to do simply by hiding the page or using ! somewhere in the parameters for find()?

Oh, and thanks again for the very helpful examples - much appreciated!

Link to comment
Share on other sites

To filter out the current rights holder, I think you'd just want to not link to it, or add some logic to the template to avoid listing those.

To not link to it, you'd just do something like this:

<?php
if($page->atype->name == 'current_rights_holder') {
    echo $page->atype->title;
} else {
    echo "<a href='{$page->atype->url}'>{$page->atype->title}</a>";
}

Or if you want to link to, but not list all the current rights holders, your atype template could have the logic instead:

<?php
if($page->name == 'current_rights_holder') {
    echo "nothing to list";
} else {
    echo $pages->find("atype=$page, limit=25")->render();
}
Link to comment
Share on other sites

Ooookay, now I've actually tried the examples posted above I love the way you guys have suggested to do it. Much quicker, if a little weird at first and more straightforward for lists that might have to be added to in future by non-programmers.

Glad you like it! That is the way how everyone feels about first. First it just feels stupid and wrong to use pages like that. Of course because we are so used to what "page" means in cms. But processwire's power and simplicity comes from simple fact that almost everything are pages. Now that I have developed little more with processwire, I am amazed how quickly I can do things... and the reason for this is that.. well, everything are pages :) I loop and find everything using same API. Even users, permissions and roles are pages (in 2.1) so you can extend (well, you probably want to extend only users) and use those just the same way than everything else.

Another thing that I suggest learning (or probably that you will learn pretty quickly just by developing with pw) are WireArrays. You will be glad to realize how great tools you have in hands every time you need those.

Link to comment
Share on other sites

  • 2 years later...

Hi everyone, I'm in my first week of ProcessWire and loving it! I've next to no php experience but I'm figuring things out thanks to all your help on this forum.

It took me about 5 attempts to understand this process but now I get it. What a clever way of doing this. It makes it so simple for the user to edit as well which is great.

Thanks folks.

  • Like 3
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...