We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 20135
    • 188 Posts
    I'm trying to create a list of staff members, with some information and a bio, as well as including some more categorisation of the members - ie, all the staff belong to the Finance dept, but a subset belong to accounting, others belong to client mgmt, etc. Each staff member occupies their own resource with their details, and I'm using getResources to display the list. However, I am trying to nest the subsets, and failing miserably.

    Here's what I've done so far. The parent folder for all staff has some staff resources, but also some subfolders with the pagetitle set as the sub-category name. I'm trying to display that structure with gR.

    Snippet call in the parent folder for all staff:
    [[getResources? &parents=`[[*id]]` &tplFirst=`gR_bodListItem1st` &tpl=`gR_bodListItem` &tplLastt=`gR_bodListItemLast` &includeTVs=`1` &sortby=`{"menuindex":"ASC","publishedon":"DESC"}` &showHidden=`1` &includeContent=`1` &hideContainers =`0` ]]


    &tplFirst (gR_bodListItemFirst):
    <ul>
    [[$gR_bodListItem]]

    &tpl (gR_bodListItem):
    [[+isfolder:eq=`1`:then=`<h2>[[getResourceField ? &id=`[[+parent]]` &field=`pagetitle`]]</h2>`]]
    						<li>
    [[+isfolder:eq=`1`
    :then=`[[!getResources? &parents=`[[+id]]` &tplFirst=`gR_bodListItem1st` &tpl=`gR_bodListItem` &tplLast=`gR_bodListItemLast` &includeTVs=`1` &sortby=`{"menuindex":"ASC","publishedon":"DESC"}` &showHidden=`1` &includeContent=`1`]]`
    :else=`
    ... staff member content, etc ...
    ` ]]
    						</li>

    &tplLast (gR_bodListItemLast):
    [[$gR_bodListItem]]
    </ul>
    

    How can I nest using getResources? I've heard it can be done, but it's just not working for me.
      • 3749
      • 24,544 Posts
      getResources isn't really designed to traverse a tree and show various levels. It may be possible to make it work, but it would be very slow and you'd have to play with making things cached and uncached to make sure the tags were parsed in the right order so their values would be available when they are used.

      You might be able to use Wayfinder, which is designed to do just that, but I'm not sure it would set all the necessary placeholders.

      Otherwise, a custom snippet using getMany('Children') and perhaps calling getResources with $modx->runSnippet() or (probably better) using toArray() and getChunk() is probably in order. [ed. note: BobRay last edited this post 14 years, 11 months ago.]
        Did I help you? Buy me a beer
        Get my Book: MODX:The Official Guide
        MODX info for everyone: http://bobsguides.com/modx.html
        My MODX Extras
        Bob's Guides is now hosted at A2 MODX Hosting
        • 3749
        • 24,544 Posts
        FYI, the custom snippet might look something like this:

        [[!ShowStaff]]


        <?php
        /* ShowStaff snippet */
        
        $departments = $modx->resource->getMany('Children');
        $output = '<h2>' . $modx->resource->get('pagetitle') . '</h2>';
        
        if (empty($departments)) {
           $output .= '    No Departments';
        } else {
            foreach ($departments as $department) {
                $output .= "\n<h3>" . $department->get('pagetitle') . '</h3>';
                $employees = $department->getMany('Children');
                if (empty($employees)) {
                    $output .= "\n    No Employees";
                } else {
                    foreach ($employees as $employee) {
                        $fields = $employee->toArray();
                        $output .= $modx->getChunk('employeeTpl', $fields);
                    }
                }
            }
        }
        
          Did I help you? Buy me a beer
          Get my Book: MODX:The Official Guide
          MODX info for everyone: http://bobsguides.com/modx.html
          My MODX Extras
          Bob's Guides is now hosted at A2 MODX Hosting
          • 20135
          • 188 Posts
          Wow, ok, thanks for that. I see what you're doing there. Got a few questions:

          1. Will this cater for employees who aren't in a department, who are just under the parent folder?
          2. I'm assuming that between toArray and getChunk, all of the fields will be outputted to placeholders set in the chunk. Can I also set what you've put as <h2> and <h3> into placeholders as something similar to &tplFirst?
          3. Can I then nest the output in the display, say in a <ul> or <dl>?
          4. Can I add a feature request to include nesting in getResources for something that should be a fairly natural progression of the component?
            • 3749
            • 24,544 Posts
            1. I don't think so, since there's no way for the program to know whether the page holds an employee or a department. You could move those employees to a folder called "General Staff" or something similar.

            2. Yes all fields are set as placeholders. You can't use placeholders for the headers unless you move them into another chunk and add another call to toArray() and getChunk() for each one.

            3. Sure, just add those to the snippet at the right place:

            $output .= '<ul>';


            4. You can request anything as a feature: https://github.com/opengeek/getResources/issues. It will be up to the author whether it's implemented or not.
              Did I help you? Buy me a beer
              Get my Book: MODX:The Official Guide
              MODX info for everyone: http://bobsguides.com/modx.html
              My MODX Extras
              Bob's Guides is now hosted at A2 MODX Hosting
              • 20135
              • 188 Posts
              Thanks for the response:

              1. What if the containers were simply weblinks? Could utilise the class key to define if a resource was a department instead of an employee. What's the method for calling the class key?

              2. That's fine. I'm using TVs for some of the employee info, how do I pull the TVs into the chunk also?

              3. Cool, easy.

              4. It looks like someone's already requested the feature. I'll keep my eye out for updates.
                • 3749
                • 24,544 Posts
                1. I wouldn't mess with the class_key. If there are no empty departments, you can just treat a department as an employee when it's empty. If that won't work, you can check the "container" checkbox for departments and not for employees. Then you can see if a "department" is really an employee by doing this:

                <?php
                if (! $department->get('isfolder')) {
                 /* it's an employee */
                }


                The way to handle TVs is basically to put placeholders in the chunk for them:

                [[+FieldName]]


                Then add them to the $fields array:

                <?php
                $fields['FieldName'] = $employee->getTVValue('TvName');
                
                [ed. note: BobRay last edited this post 14 years, 11 months ago.]
                  Did I help you? Buy me a beer
                  Get my Book: MODX:The Official Guide
                  MODX info for everyone: http://bobsguides.com/modx.html
                  My MODX Extras
                  Bob's Guides is now hosted at A2 MODX Hosting
                  • 20135
                  • 188 Posts
                  Great, that's what I was looking for. Thanks so much, will work and let you know how it goes.
                    • 20135
                    • 188 Posts
                    Ok, so I've got it close to complete. However, I have a couple of questions. First tho, the code:

                    <?php
                    /* ShowStaff snippet */
                    
                    // Get children below snippet
                    $departments = $modx->resource->getMany('Children');
                    
                    $output = '<ul class="bodul">';
                    
                    // if no children
                    if (empty($departments)) {
                      $output .= "\n\t<li>No Departments\</li>";
                    } else {
                    	foreach ($departments as $department) {
                    	  
                    		// if not published, go to next resource
                    	  	if (!$department->get('published')) continue;
                    	  
                    		// if resource is container, output pagetitle and trawl for children
                    		if ($department->get('isfolder')) {
                    			$output .= "\n\t<li>\n\t\t<ul>";
                    		  $output .= "\n\t\t\t<li><h3>" . $department->get('pagetitle') . "</h3></li>\n";
                    
                    		  	$employees = $department->getMany('Children');
                    		  
                    			if (empty($employees) ) {
                    			  $output .= "\n\t\t\t<li>No Employees</li>";
                            		
                    			} else {
                    				foreach ($employees as $employee) {
                    	  				if (!$employee->get('published')) continue;
                    					$fields = $employee->toArray();
                    					$fields['tv.bodTitle'] = $employee->getTVValue('bodTitle');
                    					$fields['tv.bodQuals'] = $employee->getTVValue('bodQuals');
                    					$fields['tv.bodEmail'] = $employee->getTVValue('bodEmail');
                    					$fields['tv.bodNumber'] = $employee->getTVValue('bodNumber');
                    					$fields['tv.bodImage'] = $employee->getTVValue('bodImage');
                    					$output .= $modx->getChunk('employeesTpl', $fields);
                    				}
                    			}
                    		  
                    			$output .= "\n\t\t</ul>\n\t</li>";
                    
                    		} else {
                    			// if resource is not a container, extract data
                    		  	$fields = $department->toArray();
                    			$fields['tv.bodTitle'] = $department->getTVValue('bodTitle');
                    			$fields['tv.bodQuals'] = $department->getTVValue('bodQuals');
                    			$fields['tv.bodEmail'] = $department->getTVValue('bodEmail');
                    			$fields['tv.bodNumber'] = $department->getTVValue('bodNumber');
                    			$fields['tv.bodImage'] = $department->getTVValue('bodImage');
                    			$output .= $modx->getChunk('employeesTpl', $fields);
                    		}
                    	}
                    }
                    
                    $output .= "\n</ul>";
                    
                    return $output;

                    1. How do I apply sorting to the items, to order them by menuindex?
                    2. How would I go about making calls for the TVs more dynamic, rather than specifying them as I have?
                      • 3749
                      • 24,544 Posts
                      For sorting, I think this will work, but I'm not sure:

                      <?php
                      $c = $xpdo->newQuery('modResource');
                      $c->sortby('pagetitle','ASC');
                      $departments = $modx->resource->getMany('Children', $c);
                      


                      Their are a number of ways to make it more dynamic, depending on where the information is coming from.

                      If it's in the snippet tag, you can just replace the appropriate values with:

                      $scriptProperties['propertyName']


                      If they're coming from a posted form, you can use:

                      $_POST['fieldName']
                        Did I help you? Buy me a beer
                        Get my Book: MODX:The Official Guide
                        MODX info for everyone: http://bobsguides.com/modx.html
                        My MODX Extras
                        Bob's Guides is now hosted at A2 MODX Hosting