Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Laura Holland 82 posts 103 karma points
    Sep 23, 2011 @ 02:03
    Laura Holland
    0

    Generate navigation from selected checkbox list values from child nodes

    I'm trying to grab the selected checkbox list datatype values from child nodes, and generate navigation links for these values that pass the value into a query string.

    I have the following node structure (Product Sub Type is what I'm trying to grab):

    So for example, on the Womens page, I'd like to have the following navigation:

    Necklaces >

    • <a href="?Gold">Gold</a>
    • <a href="?Diamond">Diamond</a>

    I can get a simple list of the selected values using this:

    <xsl:variable name="values" select="concat(./*/productSubType,',')"/>

    But I need to break them out for the navigation.. not sure how to best do that, without getting duplicates.

  • Richard 146 posts 168 karma points
    Sep 23, 2011 @ 11:31
    Richard
    0

    Laura,

    The following should give you a list of the used checkbox list items:

    <xsl:variable name="preIDProduct" select="22"/>

    <xsl:apply-templates select="umbraco.library:GetPreValues($preIDProduct)/preValue">
    <xsl:sort select="." data-type="text" order="ascending" />
    </xsl:apply-templates>


    <xsl:template match="preValue" mode="sector">

    <xsl:variable name="sectorText"><xsl:value-of select="./text()"/></xsl:variable>

    <xsl:if test="count($currentPage/node[contains(./data[@alias='sector'],$sectorText)]) &gt; 0">
    <xsl:value-of select="$sectorText"/>
    </xsl:if>

    </xsl:template>

    This is taken from an old schema site. preIDProduct is the ID of the Data Type, the logic being that GetPreValues returns all of the options, and the template preValue checks to see if it has been used, if it has it outputs the option value.

    Richard

  • Laura Holland 82 posts 103 karma points
    Sep 23, 2011 @ 17:23
    Laura Holland
    0

    Thanks Richard. I always appreciate the responses I get on this forum! Your code is giving me a list of all possible checkbox list values, not just the ones selected. Is that what it should be doing? For the purposes of this navigation, I only want the ones that were selected on the child nodes.

    Here's what I get with your code:

    What I want to get is, for example, just "Gold" and "Diamonds" under Necklaces, because they are the only two options selected on the child nodes of Necklaces.

  • Richard 146 posts 168 karma points
    Sep 23, 2011 @ 18:26
    Richard
    0

    Laura,

    We use this logic to only list checked items on a site that we created, very similar to what you want to do. I would check the workings of the if statement within the match preValue template. As this template is called for every checkbox option, the /data[@alias='sector'] is the alias of the checkbox property on the child page.

    Richard

  • Laura Holland 82 posts 103 karma points
    Sep 23, 2011 @ 20:53
    Laura Holland
    0

    Gosh, I must be dense, but I'm still not getting it. I didn't change anything in your code other than the alias & ID of the checkbox datatype.

    I tried this, which gives me everything that was selected on the child nodes, but it gives me duplicates:

    <xsl:for-each select="./*/productSubType">
              <xsl:value-of select="."/>
    </xsl:for-each>

    But this gives me a long list of duplicates: Gold,DiamondGold,DiamondGold,DiamondGold, etc.

    I want to lump them all together. I wish I could figure this out!

     

     

  • Laura Holland 82 posts 103 karma points
    Sep 24, 2011 @ 20:26
    Laura Holland
    0

    This is what I have thus far, based on the code given, but no luck:

    <xsl:param name="currentPage"/>
    <xsl:variable name="level" select="3"/>
     
      <xsl:template match="/">
    <div id="subNav">
          <ul>
            <xsl:for-each select="$currentPage/ancestor-or-self::* [@isDoc and @level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
              <li>
                <a href="{umbraco.library:NiceUrl(@id)}">
                  <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
                    <!-- we're under the item - you can do your own styling here -->
                    <xsl:attribute name="class">selected</xsl:attribute>
                  </xsl:if>
                  <xsl:value-of select="@nodeName"/>
                </a> /
                <ul>
    <xsl:variable name="preIDProduct" select="1085" />
                  <xsl:apply-templates select="umbraco.library:GetPreValues($preIDProduct)/preValue">
                    <xsl:sort select="." data-type="text" order="ascending" />
                  </xsl:apply-templates>
                </ul>
              </li>
            </xsl:for-each>
          </ul>
        </div>
      </xsl:template>

    <xsl:template match="preValue" mode="sector">

        <xsl:variable name="sectorText">
          <xsl:value-of select="./text()"/>
        </xsl:variable>
      

          <xsl:if test="count(./*/productSubType[contains(./data,$sectorText)]) &gt; 0">
          <xsl:value-of select="$sectorText"/>
        </xsl:if>

      </xsl:template>
    </xsl:stylesheet>
  • Chriztian Steinmeier 2800 posts 8791 karma points MVP 8x admin c-trib
    Sep 24, 2011 @ 22:25
    Chriztian Steinmeier
    0

    Hi Laura,

    There are two subtle things wrong (from what I can see):

    In the preValue template you forgot to use $currentPage in the test (all selections are relative to the element in the match attribute) - but then you shouldn't actually get any output at all, which led to the missing mode attribute on the template, so you need to either remove the mode="sector" from the template *or* add the mode in the apply-templates instruction.

    In fact, you could just change the preValue template to this:

    <xsl:template match="preValue">
        <xsl:if test="$currentPage/*/productSubType[contains(data, .)]">
            <xsl:value-of select="."/>
        </xsl:if>
    </xsl:template>

    (Depending on which page you call it from you may need to change the XPath a little)

    /Chriztian

     

  • Laura Holland 82 posts 103 karma points
    Sep 25, 2011 @ 01:59
    Laura Holland
    0

    Thanks Chriztian. I changed my code to this, but it's still not working:

    <xsl:param name="currentPage"/>
      <xsl:variable name="level" select="3"/>
      <xsl:variable name="preIDProduct" select="1085" />
     
      <xsl:template match="/">
        <div id="subNav">
          <ul>
            <xsl:for-each select="$currentPage/ancestor-or-self::* [@isDoc and @level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
              <li>
                <a href="{umbraco.library:NiceUrl(@id)}">
                  <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">          
                    <xsl:attribute name="class">selected</xsl:attribute>
                  </xsl:if>
                  <xsl:value-of select="@nodeName"/>
                </a>       
                <xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1']) &gt; 0">
                  <ul>
                    <xsl:apply-templates select="umbraco.library:GetPreValues($preIDProduct)/preValue">
                      <xsl:sort select="." data-type="text" order="ascending" />
                    </xsl:apply-templates>
                  </ul>          
              </xsl:if>         
              </li>
            </xsl:for-each>
          </ul>
        </div>
      </xsl:template>

      <xsl:template match="preValue">
        <xsl:if test="$currentPage/*/productSubType[contains(data, .)]">
          <li>
            <xsl:value-of select="."/>
          </li>
        </xsl:if>
      </xsl:template>

    With this code, I get a very funky output, without any values from the checkboxlist (productSubType). I basically just get the first level nodes, nested incorrectly:

    <ul>
    <li><a href="/collections/womens/necklaces.aspx">Necklaces</a>
    <ul />
    </li>
    <li><a href="/collections/womens/charms-pendants.aspx">Charms &amp; Pendants</a>
    <ul /></li>
    <li><a href="/collections/womens/pins-brooches.aspx">Pins &amp; Brooches</a><xml:text> / </xml:text><ul /></li>
    <li><a href="/collections/womens/rings.aspx">Rings</a><xml:text> / </xml:text></li></ul>

    If I add "mode="productSubType"" to the preValue template, I get all possible values of the checkboxlist, like I was before, without sorting out selected values.

     

  • Laura Holland 82 posts 103 karma points
    Sep 26, 2011 @ 22:19
    Laura Holland
    0

    Still stuck on this.. anyone out there have any ideas? Me and Tagging and Umbraco never get along... this is the second project where I got stuck on this same scenario.

  • Chriztian Steinmeier 2800 posts 8791 karma points MVP 8x admin c-trib
    Sep 26, 2011 @ 22:34
    Chriztian Steinmeier
    0

    Hi Laura,

    Could you do a <xsl:copy-of select="$currentPage/productSubType" /> on one of the pages that has this one defined?

    And if you could do another one: <xsl:copy-of select="umbraco.library:GetPreValues($preIDProduct)" /> 

    (If you're doing it in the XSLTVisualizer, rememeber to wrap a <textarea> around the copy-of so the XML doesn't get mangled by the tool)

    - We'll make it work for sure.

    /Chriztian

  • Chriztian Steinmeier 2800 posts 8791 karma points MVP 8x admin c-trib
    Sep 26, 2011 @ 22:55
    Chriztian Steinmeier
    0

    Hi again,

    Did a quick test to see what the CheckboxList actually saves - I think (without having seen the XML) you'll need to do the following:

    In the lines where you apply templates to the preValues, send the current node of the surrounding for-each along:

    <xsl:apply-templates select="umbraco.library:GetPreValues($preIDProduct)/preValue">
        <xsl:sort select="." data-type="text" order="ascending" />
        <xsl:with-param name="node" select="current()" />
    </xsl:apply-templates>

    - and receive it in the template - *and* fix the error in the contains() test:

    <xsl:template match="preValue">
        <xsl:param name="node" />
        <xsl:if test="$node/productSubType[contains(., current())]">
            <li>
                <xsl:value-of select="."/>
            </li>
        </xsl:if>
    </xsl:template>

    Only catch here is if you've got tags called "Ring" and "Gold Ring" - then you'll need to add some commas to the tests because "Gold Ring" will be printed every time "Ring" was selected too.

    /Chriztian 

  • Laura Holland 82 posts 103 karma points
    Sep 27, 2011 @ 23:13
    Laura Holland
    0

    Chriztian, you are amazing! It works beautifully!

    For posterity's sake, here's the working code, though I'm still trying to figure out how to get the  <xsl:value-of select="umbraco.library:NiceUrl(@id)"/> working correctly in the preValue template (it's giving the value of the current page, not the current node being processed -- I guess I want the $node ID value, but not sure how to get that correctly).

    <xsl:param name="currentPage"/>
      <xsl:variable name="level" select="3"/>
      <xsl:variable name="preIDProduct" select="1085" />
     
      <xsl:template match="/">
        <div id="subNav">
          <ul>
            <xsl:for-each select="$currentPage/ancestor-or-self::* [@isDoc and @level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
              <li>
                <a href="{umbraco.library:NiceUrl(@id)}">
                  <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">          
                    <xsl:attribute name="class">selected</xsl:attribute>
                  </xsl:if>
                  <xsl:value-of select="@nodeName"/>
                </a>       
                <xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1']) &gt; 0">
                  <ul>             
                    <xsl:apply-templates select="umbraco.library:GetPreValues($preIDProduct)/preValue">
                      <xsl:sort select="." data-type="text" order="ascending" />
                      <xsl:with-param name="node" select="current()" />
                    </xsl:apply-templates>
                  </ul>          
              </xsl:if>         
              </li>
            </xsl:for-each>
          </ul>
        </div>
      </xsl:template>

      <xsl:template match="preValue">
        <xsl:param name="node" />
        <xsl:if test="$node/*/productSubType[contains(., current())]">
          <li>
            <a>
              <xsl:attribute name="href" >
                <xsl:value-of select="umbraco.library:NiceUrl(@id)"/>
                <xsl:text>/?select=</xsl:text>
                <xsl:value-of select="."/>
              </xsl:attribute>
                <xsl:value-of select="."/>
            </a>
          </li>
        </xsl:if>
      </xsl:template>
     

     

  • Chriztian Steinmeier 2800 posts 8791 karma points MVP 8x admin c-trib
    Sep 27, 2011 @ 23:55
    Chriztian Steinmeier
    1

    Great, Laura

    You should be able to just do what you said, i.e.: NiceUrl($node/@id) 

    /Chriztian

  • Laura Holland 82 posts 103 karma points
    Sep 28, 2011 @ 03:18
    Laura Holland
    0

    Perfecto! I can't tell you how much I appreciate your help.

Please Sign in or register to post replies

Write your reply to:

Draft