listing checkmarked items

11 posts by 3 authors in: Forums > CMS Builder
Last Post: January 16, 2019   (RSS)

By rez - January 15, 2019 - edited: January 16, 2019

I have 3 editors. 

  1. is Locations multi with name and address field.
  2. is multi with pdf uploads, 1 each record. Currently there are 3 PDF files / records
  3. is a multi where I assign 13 locations from multi 1 to different PDF files. Some locations will be assigned the same PDF.
    1. In this editor,  you select a PDF with a drop menu using the database option, num for location name for label
    2. You then assign locations with a checkbox list

I am listing the PDF files for locations like this (my code looks right in preview but bunches up in post? It isnt what i need anyway)

// load records from 'assign' list($assignRecords, $assignMetaData) = getRecords(array( 'tableName' => 'assign', 'loadUploads' => true, 'allowSearch' => false, )); // load records from 'pdf_menus' list($pdf_menusRecords, $pdf_menusMetaData) = getRecords(array( 'tableName' => 'pdf_menus', 'loadUploads' => true, 'allowSearch' => false, )); // load records from 'locations' list($locationsRecords, $locationsMetaData) = getRecords(array( 'tableName' => 'locations', 'loadUploads' => true, 'allowSearch' => false, )); <?php foreach ($assignRecords as $record1): ?> <p><strong>Locations:</strong> <?php echo join(', ', $record1['locations:labels']); ?><br/> <?php foreach ($pdf_menusRecords as $record2): ?> <?php foreach ($record2['pdf'] as $index => $upload): ?> <?php if($record1['pdf_menu']==$record2['num']):?> Upload Url: <?php echo htmlencode($upload['urlPath']) ?><br/> <?php endif ?> <?php endforeach ?> <?php endforeach ?> </p> <?php endforeach ?>

which comes out like this:

Locations:Beltsville, Capitol Heights, Frederick, Gaithersburg
Upload Url: /cmsb/uploads/menu-01.pdf

Locations:Glen Burnie, Hagerstown, Laurel, Olney, Oxon Hill
Upload Url: /cmsb/uploads/menu-02.pdf

Locations:Philadelphia, Takoma Park / Langley Park, Temple Hills
Upload Url: /cmsb/uploads/menu-03.pdf

Which I can make link to the PDF files, no problem.

However, the client wants it each location listed separately:

Beltsville: PDF link

Capital Heights: PDF lnk

Frederick:PDF Link

etc.

That way, with many locations, they can be in alphabetical order and easier to find with one long list. 

So I tried some code I have (can see in my previous forum posts, a long time ago) that uses portfolio categories and depending on the location URL selected, lists any checkmarked items assigned to categories. Unfortunately, it's a different situation.

I wish CMSB had some built in features for this type of thing. It seems common to have to manually use arrays, explode, etc. for checkboxes. Whether it is a portfolio, tags, etc. If we are all doing it enough, it would be great if the CMS handled it. If it's common, please build it in?

Anyway, any help is appreciated.

How can I list out each location in multi 1, then loop through each PDF seeing if it is checkmarked / assigned in multi 3, and displaying only the checkmarked PDF? 

Unless there is an easier way? All I need to keep is multi 1 and can start over. My point was to not have to upload a PDF per location because there are 13 locations and only 2 or 3 PDFs with more locations on the way. 

By Toledoh - January 15, 2019

Hi Res.

Could you just add a pick list to the locations editor?  The pick list could be multiple or single only.  Then just have a list view of the locations section?

Cheers,

Tim (toledoh.com.au)

By rez - January 16, 2019 - edited: January 16, 2019

Thanks!

Yes, I could. I forgot to mention that the PDF's will change often though. That would mean I had to go into every location (which will increase) when they changed. Currently, there are only 2 PDF's. I'm trying to make only 2 edits. At some point, 20 locations and 3 PDFs. Having to go into each location works but not the most efficient for the client. I will do this in a pinch to launch though, I appreciate the suggestion.

Although there is one PDF per location, I was also building scheduling where 1 PDF could expire and another would display. You can see in my screenshot that would be easy to add into what I'm trying to do. 

I'm always getting confused when I get into these arrays, tab separations, explode, etc. I have it down for categories, listing out items that are checked for one category passed in the URL. Works great.   

Hopefully, someone may be listing checkboxes / selections like this and show some code. I'll get back to attempts and post them but it will be pretty bad. I didn't save them.

By daniel - January 16, 2019

Hi Rez,

I think that Tim's suggestion is probably the simplest way to achieve this sort of list, but as you've said, this may not be the most efficient for you to work with. However, the drawback is that the more efficient method is considerably more complex to represent on the front-end.

The following has not been fully tested and makes a few assumptions about how you've set up your lists and field names, but I believe should at least be close to what you're looking for:

<?php
// load records from 'assign' 
list($assignRecords, $assignMetaData) = getRecords(array( 'tableName' => 'assign', 'loadUploads' => true, 'allowSearch' => false, )); 
// load records from 'pdf_menus' 
list($pdf_menusRecords, $pdf_menusMetaData) = getRecords(array( 'tableName' => 'pdf_menus', 'loadUploads' => true, 'allowSearch' => false, )); 
// load records from 'locations' 
list($locationsRecords, $locationsMetaData) = getRecords(array( 'tableName' => 'locations', 'loadUploads' => true, 'allowSearch' => false, )); 

// group PDFs by num
$pdfsByNum = array_groupBy($pdf_menusRecords, 'num');

?>

<?php foreach ($locationsRecords as $locationRecord): ?> 
  <p>
  
    <strong><?php echo $locationRecord['title']; ?>:</strong> 

    <?php foreach ($assignRecords as $assignRecord): ?> 
      <?php
        // unpack multi-select values for easier searching
        $assignedLocations = listValues_unpack($assignRecord['locations']);
      ?>
      
      <?php if (array_search($locationRecord['num'], $assignedLocations) !== false): ?>
        
        <?php if (isset( $pdfsByNum[ $assignRecord['pdf_menu'] ] )): ?>
          
          <a href="<?php echo $pdfsByNum[ $assignRecord['pdf_menu'] ]['pdf']['urlPath']; ?>">PDF Download</a>
          
        <?php endif; ?>
        
      <?php endif; ?>
      
    <?php endforeach; ?>
    
  </p> 
<?php endforeach; ?>

The main things to note are:

  1. We start by looping through the locations
  2. We group the PDF records by their num to make it easy to find a PDF if we know its num
  3. Checking if a record is selected in a multi-select is more complicated (using listValues_unpack() and array_search())

I hope that's helpful; let me know if you have any questions about how this works!

Thanks,

Daniel
Technical Lead
interactivetools.com

By rez - January 16, 2019

Wow, ok. Thanks for this, it makes a perfect list. There are functions I didn't know existed or understand yet.

However, the upload links are currently coming out as "undefined index: urlPath"

They are uploads in the pdf multi, usually displayed with the standard code:

 <?php foreach ($pdf_menusRecords as $record): ?>
<?php echo htmlencode($record['title']) ?>:

  <?php foreach ($record['pdf'] as $index => $upload): ?>
   <a href="<?php echo htmlencode($upload['urlPath']) ?>" target="_blank">View PDF</a><br/>

  <?php endforeach; ?>
<?php endforeach; ?>

Also, doesn't the code have to loop through possible checkmarks,  which could even be more than one PDF per location by mistake? I'll be able to view the page and see that more than one is assigned by mistake but I'm lost adjusting your code.

Probably those assumptions you mentioned?

I will have questions about the functions but I guess i better wait on that or I'll confuse things more. 

By daniel - January 16, 2019

Hi Rez,

It looks like what's missing is the middle foreach in the snippet you just listed. Instead of "$record['pdf']" you would use "$pdfsByNum[ $assignRecord['pdf_menu'] ]['pdf']", so I think the modification would look something like this:

...
  <?php if (isset( $pdfsByNum[ $assignRecord['pdf_menu'] ] )): ?>
          
    <?php foreach ($pdfsByNum[ $assignRecord['pdf_menu'] ]['pdf'] as $index => $upload): ?>
      <a href="<?php echo htmlencode($upload['urlPath']) ?>" target="_blank">View PDF</a>
    <?php endforeach; ?>
          
  <?php endif; ?>
...

We are able to skip looping through possible checkmarks by using listValues_unpack(), which takes the values from a multi-select field (e.g. $assignRecord['locations']) and returns an array of all of the selected values. In this case, it should all be the location record nums. Then we use array_search() to effectively check "if the num for this location is in the array."

Let me know if you have any more questions. In the future, we'd love to create some documentation to make these additional functions more accessible to the average user!

Thanks,

Daniel
Technical Lead
interactivetools.com

By rez - January 16, 2019 - edited: January 16, 2019

Yes! I was assuming that's what was happening but couldn't get that loop working. I don't quite understand the nested looking array stuff. I was sure you created those functions for this type of thing and I didn't know about them. I searched and found them in the change log. 

Well, that was my next question. Documentation. Ok, is there anything I can run or test on functions that are in change logs or that I see in the forum that would sort of list out what they might do? 

If not, are there any snippets you can you show me here that might help me experiment with this setup to see more? If not, no worries, I will experiment and just ask specific questions later. I can sort of see whats happening, it's almost "readable" logic but not until I see it already done. I'm pretty sure I will end up understanding it more than %\t tab lists, explode and all of that. Embarrassingly, I get lost every time but have a collection that has worked in repeat situation with minor tweaks.

Working great and really cool, thanks.

By rez - January 16, 2019 - edited: January 17, 2019

Oh, or maybe I need to just to display the contents of the variables you are setting to see more. Something like that?

Confused: So if the unpack already figured out the checkboxes, what does the "isset" do here?

By daniel - January 16, 2019

Hi Rez,

A lot of these internal functions will have some short documentation or usage instructions right in the code if you're able to find where they are defined. array_groupBy() is in cmsb/lib/common.php on line 1204, and listValues_unpack() is in cmsb/lib/schema_functions.php on line 501. array_search() is a native PHP function and the documentation can be found here: http://php.net/manual/en/function.array-search.php

Also, a general tip that I find very helpful for testing is that you can use showme() on arrays, and var_dump() on any variable, to get a better representation of what's in them, like this:

showme( $foo ); // this is a helper function in CMSB; prints array contents
var_dump( $bar ); // this is a native PHP function; displays details of any variable (http://php.net/manual/en/function.var-dump.php)

When I'm trying out new code or functions, I find it helpful to use these functions to see a visual representation of my data at various points, such as before and after I use a function on it.

Hopefully, this gives you a good starting place!

Cheers,

Daniel
Technical Lead
interactivetools.com