XSLT menu function

Topics: Azure, Community, General, Troubleshooting, Visual editor, XSLT
Jul 26, 2012 at 11:04 AM

Hello All,

I have been searching the forum for a while but haven't found any solution.

I want an xslt menu function that will display only pages of a specific page type.

Any help on this will be appreciated.

Thank you.

Coordinator
Jul 26, 2012 at 2:17 PM

Hi @ddomdadoh

I can see that it is impossible to create a parameter of type DataReference<IPageType>, which makes things a bit more difficult.

1) Add a new inline C# function. Let's call it "Test.PageTypeSelectorOptions"

using System;
using System.Collections;
using System.Linq;
using Composite.Data;
using Composite.Data.Types;

namespace Test
{
	public static class InlineMethodFunction
	{
		public static IEnumerable PageTypeSelectorOptions()
		{
                    using(var conn = new DataConnection())
                    {
                         return conn.Get<IPageType>().ToDictionary(t => t.Id, t => t.Name);
                    }
		}
	}
}

2) To your XSLT function add a parameter "PageTypeId" of type Guid.
As a widget choose Composite.Weidgets.Selector, set "Options" to a function call to "Test.PageTypeSelectorOptions"
Set also the "Test value" to an ID of one of the existing page types.

3) In your xslt function add a function call to Composite.Data.Types.IPage.GetIPageXml
"Filter" set to FieldPredicateFilter, "PageTypeId filter" to Composite.Utils.Predicates.GuidEquals and choose the parameter "PageTypeId" you added in step 2

Now, having the list of allowed pages in your input document you can filter the ouput accordingly

<xsl:variable name="PagesOfChoosenType" select="/in:inputs/in:result[@name='GetIPageXml']/IPage" />

...
<xsl:if test="count($PagesOfChoosenType[@Id = $pageId]) > 0">
  ....
</xsl:if>

Hope this will help you.

 

P.S. I'm having a short vacation trip so won't be able to post more replies here until next Wednesday.

Jul 27, 2012 at 5:24 PM

Thank you napernik,

I have followed the steps as in your post. However, when I call the XSLT function and select the pagetype as parameter value, it loads all the pages. Please find below my function (just a little bit modification of the navigation.levelsitemap function)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl in"
	xmlns:in="http://www.composite.net/ns/transformation/input/1.0"
	xmlns="http://www.w3.org/1999/xhtml">

	<xsl:param name="level" select="/in:inputs/in:param[@name='Level']" />
	<!-- Int32 -->
	<xsl:param name="depth" select="/in:inputs/in:param[@name='Depth']" />
	<!-- Int32 -->
	<xsl:param name="parent" select="/in:inputs/in:param[@name='Parent']" />
		<xsl:param name="pagetypeid" select="/in:inputs/in:param[@name='PageTypeId']" />

	<xsl:variable name="PagesOfChoosenType" select="/in:inputs/in:result[@name='GetIPageXml']/IPage" />


	<xsl:template match="/">
		<html>
			<head>
				
			</head>
			<body>
				<xsl:apply-templates mode="Level" select="/in:inputs/in:result[@name='SitemapXml']">
					<xsl:with-param name="level" select="/in:inputs/in:param[@name='Level']" />
				</xsl:apply-templates>
			</body>
		</html>
	</xsl:template>

	<xsl:template mode="Level" match="*">
		<xsl:param name="level" />
		<xsl:if test="$level &lt; 1">
			
				<ul >
					<xsl:if test="$parent='true'">
						<xsl:apply-templates mode="Page" select=".">
							<xsl:with-param name="level" select="0" />
						</xsl:apply-templates>
					</xsl:if>
					<xsl:apply-templates mode="Page" select="./*[@MenuTitle!='']">
						<xsl:with-param name="depth" select="$depth - 1" />
					</xsl:apply-templates>
				</ul>
		</xsl:if>
		<xsl:if test="$level &gt; 0">
			<xsl:apply-templates mode="Level" select="./*[@isopen='true']">
				<xsl:with-param name="level" select="$level - 1" />
			</xsl:apply-templates>
		</xsl:if>
	</xsl:template>

	<xsl:template mode="Page" match="*">
		<xsl:param name="depth" >0</xsl:param>
		<xsl:param name="level" select="/in:inputs/in:param[@name='Depth'] - $depth - 1" />
		<li>
			<xsl:attribute name="class">
				<xsl:text>level</xsl:text>
				<xsl:value-of select="$level" />
				<xsl:if test = "@isopen='true'">
					<xsl:text> NavigationOpen</xsl:text>
				</xsl:if>
				<xsl:if test = "@iscurrent='true'">
					<xsl:text> NavigationSelected</xsl:text>
				</xsl:if>
				<xsl:if test="$level = '0'">
					<xsl:text> mainarea</xsl:text>
					<xsl:choose>
						<xsl:when test="$parent='true' and $depth != 0">
							<xsl:value-of select="position()+1"/>
						</xsl:when>
						<xsl:otherwise>
							<xsl:value-of select="position()"/>
						</xsl:otherwise>
					</xsl:choose>
				</xsl:if>
			</xsl:attribute>
			<a href="{@URL}">
				<xsl:if test="@isopen='true'">
					<xsl:attribute name="class">NavigationOpen</xsl:attribute>
				</xsl:if>
				<xsl:if test="@iscurrent='true'">
					<xsl:attribute name="class">NavigationSelected</xsl:attribute>
				</xsl:if>
				<xsl:value-of select="@MenuTitle" />
			</a>
			<xsl:if test="count(./*)>0 and $depth != 0">
				<ul class="level{/in:inputs/in:param[@name='Depth'] - $depth}">
					<xsl:apply-templates mode="Page" select="./*[@MenuTitle!='']">
						<xsl:with-param name="depth" select="$depth - 1" />
					</xsl:apply-templates>
				</ul>
			</xsl:if>
		</li>
	</xsl:template>

</xsl:stylesheet>

 

 

Please what am I doing wrong?

Thanks

Coordinator
Aug 1, 2012 at 7:49 AM

you didn't implement the actual filtering part in xslt, something like this should do:

 

<xsl:template mode="Page" match="*">
	<xsl:variable name="PageId" select="@Id" />
	<xsl:if test="count($PagesOfChoosenType[@Id = $PageId]) > 0">
  
  
		<xsl:param name="depth" >0</xsl:param>
		<xsl:param name="level" select="/in:inputs/in:param[@name='Depth'] - $depth - 1" />
		
		
		<li>
			....
		</li>
		
	</xsl:if>
<xsl:template>

Aug 8, 2012 at 4:32 PM

Thank you napernik,

It works now.

I am grateful.