We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 34127
    • 135 Posts
    First off, I wanted to say that the new element properties are awesome. I like how snippet parameters are all in one central place, and I’ve been using them in a couple of my updated snippets for awhile now. grin

    I was just wondering about best practice solutions to using these properties with AJAX functionality. For example, awhile back I upgraded my poll snippet to work with revolution. It uses AJAX extensively (while degrading nicely for browsers without JS/AJAX support) but without a request handler. It basically calls the current page and just calls exit() to prevent anything other than the snippet output from being displayed. Obviously, this isn’t the optimal way to do this, since MODx loads up all sorts of unneeded stuff on this type of request.

    So I wrote a request handler and managed to get it working, *BUT* $scriptProperties obviously isn’t loaded in the external handler. You can get around this by using something like this in your AJAX processor:
    $snippet = $modx->getObject( 'modSnippet', array( 'name' => 'SnippetName' ) );        
    $scriptProperties = $snippet->getProperties();


    The issue is from the fact that users can still use parameters in the actual snippet call, to override the properties in the MODx database. In that case, the overridden properties won’t match the properties in the Element’s properties, so some pretty weird stuff could happen. I guess there’s no way around this, but would the ideal solution be for the user to simply create a new "Properties Set", override the default parameters with their own, and modify the code snippet above to get the properties from the new set instead?

    The other issue is with things like page links. A number of times I use something like $modx->makeUrl( $modx->resourceIdentifier, ’’, ’some=parameters’ ), but with an AJAX call using a handler, it isn’t a "resource" so makeURL chokes. Leaving the URL blank isn’t an option as certain parameters (ie poll_id) are used to create the onclick handler (plus, if JS is disabled, the link no longer works).

    Any ideas on either of these issues? Thanks!
      • 22303 MODX Staff
      • 10,725 Posts
      I’m a bit lost here. Let’s back up...
      Quote from: Ricjustsaid at Jan 13, 2009, 06:12 PM

      I was just wondering about best practice solutions to using these properties with AJAX functionality. For example, awhile back I upgraded my poll snippet to work with revolution. It uses AJAX extensively (while degrading nicely for browsers without JS/AJAX support) but without a request handler. It basically calls the current page and just calls exit() to prevent anything other than the snippet output from being displayed. Obviously, this isn’t the optimal way to do this, since MODx loads up all sorts of unneeded stuff on this type of request.
      This is not true; Revolution is made especially for the purpose of executing any kind of PHP request, including your AJAX requests, through a standard gateway, or through specific gateways now with contexts (i.e. consider using a context for your custom AJAX connectors), to make sure security standards, sessions, and other details are all consistent across requests, and that you can easily manage your AJAX connectors as you would any other MODx Resource. So I would say if you are writing request handlers that do not extend the modRequest class and execute in a custom context, you aren’t really using AJAX in MODx in an optimal way.

      Quote from: Ricjustsaid at Jan 13, 2009, 06:12 PM

      So I wrote a request handler and managed to get it working, *BUT* $scriptProperties obviously isn’t loaded in the external handler. You can get around this by using something like this in your AJAX processor:
      $snippet = $modx->getObject( 'modSnippet', array( 'name' => 'SnippetName' ) );        
      $scriptProperties = $snippet->getProperties();

      $scriptProperties is available anytime you call $modx->runSnippet() or instantiate the object as you did above and call $snippet->process(). I’m not clear on the problem you are trying to solve here. You should never have to call $snippet->getProperties() unless you are building a management interface or some other core extension to work specifically with properties as definitions. $scriptProperties is automatically aggregated at run-time, when processing an Element, as are all properties for any Element type.

      Quote from: Ricjustsaid at Jan 13, 2009, 06:12 PM

      The issue is from the fact that users can still use parameters in the actual snippet call, to override the properties in the MODx database. In that case, the overridden properties won’t match the properties in the Element’s properties, so some pretty weird stuff could happen. I guess there’s no way around this, but would the ideal solution be for the user to simply create a new "Properties Set", override the default parameters with their own, and modify the code snippet above to get the properties from the new set instead?
      huh That’s not an issue in my estimation; that’s by design. How is overriding the property sets in a tag an issue? To me that’s a powerful feature and was the whole intention of having default properties separate from property sets and tag properties, and allowing both property sets and tag properties to override the default. Maybe I’m confused on the what we are discussing exactly...

      Quote from: Ricjustsaid at Jan 13, 2009, 06:12 PM

      The other issue is with things like page links. A number of times I use something like $modx->makeUrl( $modx->resourceIdentifier, ’’, ’some=parameters’ ), but with an AJAX call using a handler, it isn’t a "resource" so makeURL chokes. Leaving the URL blank isn’t an option as certain parameters (ie poll_id) are used to create the onclick handler (plus, if JS is disabled, the link no longer works).
      IMO, it should be a Resource. Otherwise, your code needs to be responsible for generating the URLs of the request handlers outside the framework.
        • 28215
        • 4,149 Posts
        Quote from: Ricjustsaid at Jan 13, 2009, 06:12 PM

        Any ideas on either of these issues? Thanks!

        I would recommend making a Resource that has a template of (blank), setting its content type to JS (you’re returning JSON, right?), and then putting inside its content field your snippet. I do something similar with a snippet I’ve been developing, that goes like so:

        [[!Sherpa? &context=`connector`]]
        


        And my snippet loads the proper things necessary to output the JS. It’s up to you, however, on how you want to do it, in the end.
          shaun mccormick | bigcommerce mgr of software engineering, former modx co-architect | github | splittingred.com
          • 34127
          • 135 Posts
          Quote from: OpenGeek at Jan 13, 2009, 06:44 PM

          This is not true; Revolution is made especially for the purpose of executing any kind of PHP request, including your AJAX requests, through a standard gateway, or through specific gateways now with contexts (i.e. consider using a context for your custom AJAX connectors), to make sure security standards, sessions, and other details are all consistent across requests, and that you can easily manage your AJAX connectors as you would any other MODx Resource. So I would say if you are writing request handlers that do not extend the modRequest class and execute in a custom context, you aren’t really using AJAX in MODx in an optimal way.
          Maybe I’m approaching this the wrong way, then? My external request handler (handler.php) somewhat mirrors the ones used in the manager, and looks like this:
          <?php
          
          /**
           * This is our base connector file, for use with AJAX requests in the frontend.
           * It mainly just sets up some initial settings and instantiates the main MODx class.
           * 
           * @package ajaxpoll
           * @subpackage processors.ajaxpoll
           * @version 1.0
           * @author [snip]
           */
          
          $basePath = dirname( dirname( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) ) );
          $pollPath = dirname( dirname( dirname( __FILE__ ) ) );
          
          require_once( $basePath . '/config.core.php' );
          
          if( !defined( 'MODX_CORE_PATH' ) ) {
              define( 'MODX_CORE_PATH', $basePath . '/core/' );
          }
          
          require_once( MODX_CORE_PATH . 'model/modx/modx.class.php' );
          
          $modx = new modX();
          $modx->setDebug( E_ALL & ~E_NOTICE );
          $modx->setLogLevel( MODX_LOG_LEVEL_ERROR );
          $modx->setLogTarget( 'HTML' );
          $modx->initialize( 'connector' );
          $modx->getRequest();
          $modx->request->sanitizeRequest();
          $modx->request->handleRequest( array( 
              'location'          => 'frontend', 
              'action'            => '', 
              'processors_path'   => $pollPath . '/core/processors/'
          ) );
          
          ?>
          


          It’s simple, but it seems to work. I couldn’t find another example to model mine after. So in "best practice", I would create a new context (something like "ajax"), and create a custom request handler modeled after modRequest (kind of like modManagerRequest)?

          Quote from: OpenGeek

          $scriptProperties is available anytime you call $modx->runSnippet() or instantiate the object as you did above and call $snippet->process(). I’m not clear on the problem you are trying to solve here. You should never have to call $snippet->getProperties() unless you are building a management interface or some other core extension to work specifically with properties as definitions. $scriptProperties is automatically aggregated at run-time, when processing an Element, as are all properties for any Element type.
          In that snippet, I instantiated the snippet in order to grab the properties in my external handler script; it wasn’t a resource or anything and I wasn’t quite sure how else to get the snippet properties. tongue

          Quote from: OpenGeek

          huh That’s not an issue in my estimation; that’s by design. How is overriding the property sets in a tag an issue? To me that’s a powerful feature and was the whole intention of having default properties separate from property sets and tag properties, and allowing both property sets and tag properties to override the default. Maybe I’m confused on the what we are discussing exactly...
          Oh, I meant it was an issue with my whole solution to the AJAX handler problem, not MODx at all. In fact, that was one of the things that drew me to MODx back in the 092 days. One example would be with pagination, I have a setting "polls_pp" which determines the max number of polls to show on the archive page. I have the snippet properties setting at 15, and I have it set to 5 on the actual snippet page (to test pagination). On a regular (non AJAX) request, it uses the overridden setting (5). During the AJAX request, it uses the setting defined in the manager (15), which results in a different number of polls showing. I can imagine other oddities happening (ie. settings like vote_time, or use_cookie), but I don’t think there’s any way around it anyways.

          Quote from: OpenGeek

          IMO, it should be a Resource. Otherwise, your code needs to be responsible for generating the URLs of the request handlers outside the framework.
          That makes more sense - maybe I was overthinking this entire thing? It’s not a terribly complicated snippet, so maybe creating an external request handler and multiple processors for different requests was overkill? lipsrsealed

          Quote from: splittingred at Jan 13, 2009, 10:41 PM

          Quote from: Ricjustsaid at Jan 13, 2009, 06:12 PM

          Any ideas on either of these issues? Thanks!

          I would recommend making a Resource that has a template of (blank), setting its content type to JS (you’re returning JSON, right?), and then putting inside its content field your snippet. I do something similar with a snippet I’ve been developing, that goes like so:

          [[!Sherpa? &context=`connector`]]
          


          And my snippet loads the proper things necessary to output the JS. It’s up to you, however, on how you want to do it, in the end.

          Yep, all of my AJAX stuff outputs JSON since libraries like jQuery play nice with it. laugh Doing it this way would pretty much remove the need of having custom request handlers and such, and it would easily let users override whatever settings they want. Thanks, I’ll give it a try!