We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 45118
    • 123 Posts
    I can't seem to figure out how I can have a viewer choose the way they want to display the products on the products page. I want them to be able to choose to sort by 'height' or 'width' or even select a group ('cat') from the within products.

    I can make the different snippets. This one is the default [[ShowProds]] and the snippet call is placed in the resource prod1.html:
    <?php
    $path = MODX_CORE_PATH . 'components/aeiproducts/';
    $result = $modx->addPackage('aeiproducts',$path .
        'model/','aei_');
    
    if (! $result) {
        return 'failed to add package';
    }
    
    $products = $modx->getCollection('Product');
    foreach($products as $product) {
        $fields = $product->toArray();
        $output .= $modx->getChunk('ShowProds');
    }
    
    return $output;
    ?>

    And this one will for instance order the product by height in ascending order [[ShowProds_sortH]]:
    <?php
    $path = MODX_CORE_PATH . 'components/aeiproducts/';
    $result = $modx->addPackage('aeiproducts',$path .
        'model/','aei_');
    
    if (! $result) {
        return 'failed to add package';
    }
    
    $c = $modx->newQuery('Product');
    $c->sortby('height','ASC');
    
    $products = $modx->getCollection('Product',$c);
    foreach($products as $product) {
        $fields = $product->toArray();
        $output .= $modx->getChunk('ShowProds');
    }
    
    return $output;
    ?>

    And this one will only show the products from the category 'CAT' [[ShowProds_showCat]]:
    <?php
    $path = MODX_CORE_PATH . 'components/aeiproducts/';
    $result = $modx->addPackage('aeiproducts',$path .
        'model/','aei_');
    
    if (! $result) {
        return 'failed to add package';
    }
    
    $c = $modx->newQuery('Product');
    $c->where(array('cat'=>'CAT'));
    
    $products = $modx->getCollection('Product',$c);
    foreach($products as $product) {
        $fields = $product->toArray();
        $output .= $modx->getChunk('ShowProds');
    }
    
    return $output;
    ?>

    I could place the [[ShowProds_sortH]] and [[ShowProds_showCat]] snippets each in a new resource, prod2.html and prod3.html, and link to it from prod1.html, but I don't want to do it that way. How can I do this dynamically?

    Can someone point me in the right direction? Thank you in advance!

    This question has been answered by BobRay. See the first response.

      • 28042 ☆ A M B ☆
      • 24,524 Posts
      You can use one snippet, with variables for the sorting criteria and filtering. Get these variables from the POST of a form. The form will be on the page, with radio buttons, check boxes, or drop-down selects as seems appropriate. You can ether refresh the page, or use AJAX to post the form.

      Style the checkboxes and radio buttons so they don't look like standard form fields if you like. Have each option be a pretty button, and use AJAX to change the view when the button gets clicked. Be creative!

      http://jqueryui.com/button/#default
        Studying MODX in the desert - http://sottwell.com
        Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
        Join the Slack Community - http://modx.org
        • 3749
        • 24,544 Posts
        If possible, I would do it with a single snippet that used the information from the user to customize the query.

        You could do it with JS and an Ajax call (in which case the "snippet" would actually be a processor) or by having the user submit a form with options selected in the form.

        ExtJS/modExt does the grids in the Manager and some extras with modExt. They can often be sorted on any field (either way) by clicking on the column heading or a drop-down arrow. You can also add a search filter to limit the output.

        The Batcher extra is a good example. The CMP that comes with MyComponent is another.

        In theory, you can use CSS to make the "grid" look however you want it to.

        You might also be able to do this with MIGX.
          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
          • 45118
          • 123 Posts
          Quote from: sottwell at Sep 25, 2013, 12:18 PM
          You can use one snippet, with variables for the sorting criteria and filtering. Get these variables from the POST of a form. The form will be on the page, with radio buttons, check boxes, or drop-down selects as seems appropriate. You can ether refresh the page, or use AJAX to post the form.

          Style the checkboxes and radio buttons so they don't look like standard form fields if you like. Have each option be a pretty button, and use AJAX to change the view when the button gets clicked. Be creative!

          http://jqueryui.com/button/#default
          Hi Susan,
          I see what you mean. I think I can make the form with the drop-down selects, but I don't know how to make it "talk" to the snippet, how to process the selection. My knowledge of Modx is still very limited... sad
          This is how I changed to snippet per your suggestion. I made different variables for the different ways of sorting but I don't know if this is correct.
          <?php
          $path = MODX_CORE_PATH . 'components/aeiproducts/';
          $result = $modx->addPackage('aeiproducts',$path .
              'model/','aei_');
          
          if (! $result) {
              return 'failed to add package';
          }
          
          $cw = $modx->newQuery('Product');
          $cw->sortby('width','ASC');
          
          $ch = $modx->newQuery('Product');
          $ch->sortby('height','ASC');
          
          $cc = $modx->newQuery('Product');
          $cc->where(array('cat'=>'CAT'));
          
          $products = $modx->getCollection('Product');
          foreach($products as $product) {
              $fields = $product->toArray();
              $output .= $modx->getChunk('ShowProds');
          }
          
          return $output;
          ?>

          Thanks for all your help!
            • 28042 ☆ A M B ☆
            • 24,524 Posts
            The form works like any form, its action will be the same page, and the snippet grabs the POST to get the variables to use for sorting and filtering. Set a sane default for the case where the POST is not set.

            <?php
            $sortby = isset($_POST['sortby')) ? $_POST['sortby') : 'height';
            $sortdir = isset($_POST['sortdir'])) ? $_POST['sortdir'] : 'ASC';
            $filter = isset($_POST['filter'])) ? $_POST['filter']] : 'CAT';
            // repeat for all the POST values the form can send
            
            $query = $modx->newQuery('Product');
            $query->sortby($sortby,$sortdir);
            $query->where(array('cat'=>$filter));
            

            I'm pretty sure xPDO automatically sanitizes your input, see https://forums.modx.com/thread/82128/security-problem-if-not-sanitizing-data-before-saving-by-xpdo-to-a-database
              Studying MODX in the desert - http://sottwell.com
              Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
              Join the Slack Community - http://modx.org
              • 28042 ☆ A M B ☆
              • 24,524 Posts
              Since the first time the page is loaded, of course the POST won't be set at all, so all the defaults will be used to initially display. Once the user makes a different selection, then the page will refresh with the new output.
                Studying MODX in the desert - http://sottwell.com
                Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                Join the Slack Community - http://modx.org
                • 45118
                • 123 Posts
                Quote from: BobRay at Sep 25, 2013, 12:27 PM
                If possible, I would do it with a single snippet that used the information from the user to customize the query.

                You could do it with JS and an Ajax call (in which case the "snippet" would actually be a processor) or by having the user submit a form with options selected in the form.

                ExtJS/modExt does the grids in the Manager and some extras with modExt. They can often be sorted on any field (either way) by clicking on the column heading or a drop-down arrow. You can also add a search filter to limit the output.

                The Batcher extra is a good example. The CMP that comes with MyComponent is another.

                In theory, you can use CSS to make the "grid" look however you want it to.

                You might also be able to do this with MIGX.
                Hi Bob,
                I looked into your suggestions but it seems to me those are more for back-end solutions. For this project I need the drop down on the front-end. But thanks for your input all the same.
                  • 45118
                  • 123 Posts
                  Quote from: sottwell at Sep 26, 2013, 12:07 PM
                  The form works like any form, its action will be the same page, and the snippet grabs the POST to get the variables to use for sorting and filtering. Set a sane default for the case where the POST is not set.

                  <!--?php
                  $sortby = isset($_POST['sortby')) ? $_POST['sortby') : 'height';
                  $sortdir = isset($_POST['sortdir'])) ? $_POST['sortdir'] : 'ASC';
                  $filter = isset($_POST['filter'])) ? $_POST['filter']] : 'CAT';
                  // repeat for all the POST values the form can send
                  
                  $query = $modx--->newQuery('Product');
                  $query->sortby($sortby,$sortdir);
                  $query->where(array('cat'=>$filter));
                  

                  I'm pretty sure xPDO automatically sanitizes your input, see https://forums.modx.com/thread/82128/security-problem-if-not-sanitizing-data-before-saving-by-xpdo-to-a-database
                  Okay, I made some headway but it's not working yet!
                  Here's my snippet with Sue's suggestions worked in:
                  <?php
                  $path = MODX_CORE_PATH . 'components/aeiproducts/';
                  $result = $modx->addPackage('aeiproducts',$path .
                      'model/','aei_');
                  
                  if (! $result) {
                      return 'failed to add package';
                  }
                  
                  $sortN = isset($_POST['sortbyname']) ? $_POST['sortbyname'] : 'itemno';
                  $sortH = isset($_POST['sortbyheight']) ? $_POST['sortbyheight'] : 'height';
                  $sortW = isset($_POST['sortbywidth']) ? $_POST['sortbywidth'] : 'width';
                  $filter = isset($_POST['filter']) ? $_POST['filter'] : 'CAT';
                   
                  $c = $modx->newQuery('Product');
                  $c->sortby($sortN,'ASC');
                  $c->sortby($sortH,'ASC');
                  $c->sortby($sortW,'ASC');
                  $c->where(array('cat'=>$filter));
                  
                  $products = $modx->getCollection('Product', $c);
                  foreach($products as $product) {
                      $fields = $product->toArray();
                      $output .= $modx->getChunk('ShowProds', $fields);
                  }
                  
                  return $output;

                  And this is the code for the form (ie. the dropdown). It's placed directly in the resource above the call for the snippet:
                  <form action="[[~[[*id]]]]" method="POST">
                  <select name="sort" onchange="this.form.submit()">
                     <option value="sortbyname">Sort by Name</option>
                     <option value="sortbyheight">Sort by Height</option>
                     <option value="sortbywidth">Sort by Width</option>
                     <option value="filter">Only Show This Category</option>
                  </select>
                  <noscript><input type="submit" value="Submit"></noscript>
                  </form>

                  I'm getting some results, but not the right ones:
                  - The page shows only the one category of products, but the filter shouldn't have been selected by default
                  - When I select Height, Width or Category, it jumps back to Sort by Name

                  So in the form it seems that submit on change doesn't work plus something is off with the variables in the snippet.

                  Again, any help is very appreciated!
                    • 3749
                    • 24,544 Posts
                    It appears that you only want to sort by one attribute. In that case you only want one sort variable and one sortby statement as in Susan's example.

                    I'm not sure I understand what you're trying to do. You have 'filter' in the array of sort options but it isn't really a sort option. Maybe it should be a separate input, outside the sort options, which would allow users to select the filter *and* a sort option. Also, shouldn't there be a way for the user to select a category to show, or is there only one category available there?
                      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
                      • 45118
                      • 123 Posts
                      Quote from: BobRay at Sep 27, 2013, 05:41 PM
                      It appears that you only want to sort by one attribute. In that case you only want one sort variable and one sortby statement as in Susan's example.

                      I'm not sure I understand what you're trying to do. You have 'filter' in the array of sort options but it isn't really a sort option. Maybe it should be a separate input, outside the sort options, which would allow users to select the filter *and* a sort option. Also, shouldn't there be a way for the user to select a category to show, or is there only one category available there?
                      Hi Bob,
                      You're right, I shouldn't try to do the sorting and filtering all together. Let's backtrack and I'll try to explain what I want to accomplish. My project is something like a product catalog (no cart function included though). The website has a few dozen pages with different groups of products on it. One group can consist of a hundred products or five. The large groups can consist of 2 or more categories. My snippet so far allows me to grab the product information from a group of products from the database and with a chunk for the layout it displays nicely on the page.
                      What I'm trying to do now is give the viewer the option to sort the products on the page. Kind of like the way a shopping site lets you sort by price. I this case there would be 2 choices, by height and by width (eventually even more choices, depending on the group of products on the page), with the default setting by name. So I'd need a drop down where someone can select their choice. So far so good.
                      Now what I don't understand is how to set up my drop down on the page so that the snippet understands when someone for instance selects the sort by height value. And I also don't seem to be able to figure out how I can rework Susan's example into one that gives the viewer more than one sorting choice.

                      I've been trying many different scenarios, none of them work, so I think my way of trying to solve this might be wrong on a concept level. Any and all help is very much appreciated!