We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 14877
    • 110 Posts
    MODX Revolution 2.3.1

    I like to use MDOX: The Officil Guide (MTOG) for information and, if the topic is covered, I usually can work things out for myself. However I have run into a problem and I don't know whether there is a defect (bug) or I have miscoded/misunderstood something.

    The particular topic is "Replacing Conditional Modifiers with a Snippet" (pg 280ff).

    There is a place-holder being set in the Registration process (using the Login package). The particular place-holder is an error message [[+error.username]]. There are others, but I'm using this as an example.

    Now that place-holder is either "empty" or a text string. When a text string is set as the value, it is now wrapped in HTML tags (good!). Now all the examples of setting up a Registration form TPL chunk that I have seen embed the error-message place-holder in HTML tags such as <span class="xxx"> and </span>. I don't happen to like generating empty HTML code that does nothing useful; however, that is not an option as the HTML I want to wrap the error-message in results in extraneous white-space when it is "empty'.

    So, the solution seems to be to have a Snippet test the value of the place-holder and return the appropriate "output" — an empty string or the error-message wrapped in HTML markup. So we have the following example code in MTOG:

    /* Code for the YesNo Snippet */
    if ($value) {
        $output = 'Yes';
    } else {
        $output = 'No';
    }
    return $output;


    Now $value is simply a tag (it happens to be a resource field in the example) and the code implies it can successfully check the actual value after the tag passed as a property has been evaluated.

    So fine, I created the following code (in a snippet):

    if (empty($value)):
        return '';
    else:
        return $beginHtml . $value . $endHtml;
    endif;


    However, after a lot of experimenting and testing, it became abundantly clear that the unevaluated tag is what the snippet code is "seeing". It always returns the HTML code — sometimes with nothing in it; sometimes with an error message (when appropriate).

    The snippet invocation looks like this (if it helps understand what is happening):

    [[WrapNotEmpty?
        &beginHtml=`<br /><span class="error">`
        &value=`[[+error.username]]`
        &endHtml=`</span>`
    ]]


    Any ideas?
      __________________
      JRG
      • 3749
      • 24,544 Posts
      If &value is the unprocessed tag, you could identify it with this, but I'm not sure it will solve your problem:

      if (strpos($value, '[[') !== false) {
         /* We got the tag */
      }
        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
        • 14877
        • 110 Posts
        Quote from: BobRay at Sep 25, 2014, 06:32 PM
        If &value is the unprocessed tag, you could identify it with this, but I'm not sure it will solve your problem:

        if (strpos($value, '[[') !== false) {
           /* We got the tag */
        }
        I did something like that to verify that what I thought was happening, was in fact happening. I did that before making the original post.
        As you supposed, knowing that only identifies the problem.

        So, does your example from MTOG still work?
          __________________
          JRG
          • 4172
          • 5,888 Posts
          I think you should try to call everything with uncached tags

          [[!WrapNotEmpty?
              &beginHtml=`<br /><span class="error">`
              &value=`[[!+error.username]]`
              &endHtml=`</span>`
          ]]
            -------------------------------

            you can buy me a beer, if you like MIGX

            http://webcmsolutions.de/migx.html

            Thanks!
            • 3749
            • 24,544 Posts
            As far as I know, it does.

            Make sure that the snippet that sets the +error.username placeholder is above the WrapNotEmpty tag on the page. If it's not, that would explain what's happening to you.
              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
              • 14877
              • 110 Posts
              Quote from: BobRay at Sep 26, 2014, 09:48 PM
              As far as I know, it does.

              Make sure that the snippet that sets the +error.username placeholder is above the WrapNotEmpty tag on the page. If it's not, that would explain what's happening to you.
              The snippet invocation that set the placeholder is above the WrapNotEmpty tag.

              Bruno17 suggested a shotgun approach of making everything not cachable. I dislike guessing like that. However, after thinking about it a bit, I decided to make the snippet invocations in the following test code, unchacheable.

              <h2>Testing the WrapNotEmpty Snippet</h2>
              [[!SetTestPlaceholder?
                  &theValue=`xxxxxxxx`
              ]]
              
              [[!WrapNotEmpty?
                  &beginHtml=`<p style="text-align: center;">`
                  &value=`[[+MyTestValue]]`
                  &endHtml=`</p>`
              ]]


              The first snippet just sets a place-holder ("MyTestValue"). The above works (I tried it with &theValue=`` and with &theValue=`xxxxxxxx` (as above). WrapNotEmpty detects the difference. Hats off to Bruno17!

              However, if I make it uncacheable, then I get the problem behaviour. Bizarre. It's beginning to look like all snippet invocations should be made uncacheable. If that is the case, then it should be automatic MODX behaviour.

              I haven't (yet) tested this workaround in the real code. You might also want to retest your example from MTOG (but use a place-holder rather than a TV).
                __________________
                JRG
                • 3749
                • 24,544 Posts
                Snippets have always had to be called uncached if they will return different results at different times. Otherwise, you're just going to get the result from the last time the snippet result was cached.

                Some snippets, though, always return the same result. Those can be called cached to speed up page loads.
                  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
                  • 4172
                  • 5,888 Posts
                  Not sure, where [[+error.username]] is coming from, but I would assume, it is a placeholder, which has todo with the currently logged in user.
                  And I would assume, this placeholder is coming from an uncached snippet?

                  If the snippet was set by an cached snippet, then you can use it also in another cached snippet-call, to do something with it.

                  As soon as the placeholder can change from request to request, for example with different users logged in, you need to call the snippets, which are doing something with it also uncached, of course.

                  You could wrapp everthing in a getCache - snippet - call, so every different request could have its own cached version.

                    -------------------------------

                    you can buy me a beer, if you like MIGX

                    http://webcmsolutions.de/migx.html

                    Thanks!
                    • 14877
                    • 110 Posts
                    Quote from: BobRay at Sep 27, 2014, 10:38 PM
                    Snippets have always had to be called uncached if they will return different results at different times. Otherwise, you're just going to get the result from the last time the snippet result was cached.

                    Some snippets, though, always return the same result. Those can be called cached to speed up page loads.

                    It's not a question of whether the snippet returns different results at different times, it's whether the property being passed to the snippet is evaluated or not. If the snippet can detect that one of its properties is empty(), then the property has been evaluated; if the snippet can detect that the value of one of its properties is "[[+name-of-placeholder]]", then the property has not been evaluated before being passed to the snippet.

                    Your example from MTOG was coded as cacheable and you indicate it returns the expected values; but it returns different results at different times (sometimes "Yes", sometimes "No").

                    In my case, the difference in results only occurs when the value being passed is "empty". If it is some non-empty string, then the result is always the expected one (i.e. the place-holder tag is evaluated prior to being passed as the property value), regardless of whether the snippet invocation is marked uncacheable or not. On the the other hand, if the place-holder tag evaluates to "empty", then I get different results depending on whether the snippet invocation is marked cacheable or not.
                      __________________
                      JRG
                      • 14877
                      • 110 Posts
                      Quote from: Bruno17 at Sep 28, 2014, 06:26 AM
                      Not sure, where [[+error.username]] is coming from, but I would assume, it is a placeholder, which has todo with the currently logged in user.
                      And I would assume, this placeholder is coming from an uncached snippet?

                      If the snippet was set by an cached snippet, then you can use it also in another cached snippet-call, to do something with it.

                      As soon as the placeholder can change from request to request, for example with different users logged in, you need to call the snippets, which are doing something with it also uncached, of course.

                      You could wrapp everthing in a getCache - snippet - call, so every different request could have its own cached version.

                      The actual context involves use of the Login package. The "Register" snippet invocation (uncached) is followed by a form with text (and other) entry fields. The place-holder occurs after one of the fields (it's actually called "username"). As generally occurs with a form, the form submission causes the "page" to be "redisplayed"; that is, re-evaluated and sent to the browser. That means the place-holder may end up with a different value (an error message) the second time around (it depends on whether or not the form field had an error).

                      [Aside]My intention was/is to display the error message associated with each of the fields using a snippet to wrap HTML mark-up around the value.

                      Since the Login package uses "controllers", working out the processing exactly means reading all the code, I wrote a tiny snippet to set a place-holder to a passed value. That simplified what was going on and made the testing easier.

                      It's looking as though a snippet that is passed a tag (or at least a place-holder tag) that might have an empty value, must be made uncacheable regardless of whether it essentially returns a static result.
                        __________________
                        JRG