How to display a list of sub-pages AND their content on parent page?

How to display a list of sub-pages AND their content on parent page? 

I know you can put 'exceprt' on every page and display excerpts on parent page. But:

  • performance of this solution is unacceptably low
  • excerpt are are 'broken' for 'children display' and for 'page tree'

Any solution?

9 answers

1 accepted

This widget could not be displayed.

@Davin Studer's macro has been updated a little bit (code on github) with some new options (page separator, PDF page splitting and filtering on labels).

Davin Studer Community Champion Jan 27, 2016

I like what you have added.

I especially like the page break on PDF export. My only suggestion is that if the page separator is employed, it does not appear in the PDF if PDF page splitting is used.

Tnx for the idea Milo - the new version pushed to the github has your suggested change smile

Awesome! I can't tell you how long I've been looking for a solution to export a collection of pages to PDF with page breaks; fantastic solution.

Is there a way to get all the descendants of the given page, instead of just the children? I would like to display the contents of not only the first-level children, but also all the children in the other levels. Can an option for this be implemented?

Hello @Gregor Mirai, 

I'm attempting with very limited coding skills to modify this code to  add it to Sidebar. We want to display the current parent and its children. All other parent and child pages should be hidden.

Has anyone done this? Any insight would be greatly appreciated!

@Davin Studer This is such a great macro!  Is there anyway to add the ability for it to show all descendants not just the child pages? It would be greatly appreciated!

Thanks!

This widget could not be displayed.
Davin Studer Community Champion Dec 04, 2014

What about a user macro like this?

## Developed by: Davin Studer
## Date created: 12/4/2014
 
## @param ShowTitle:title=Show Title|type=boolean|desc=Deselect to remove the title of the child page.|default=true
## @param LinkTitle:title=Link Title|type=boolean|desc=Select to turn the titles of the child pages into links to those pages (Show Title must be selected).|default=false
## @param Order:title=Order|type=enum|enumValues=Nav Order,Reverse Nav order,Alphabetical,Reverse Alphabetical,Create Date,Reverse Create Date|default=nav order|desc=What order should the child pages be displayed? Nav Order refers to the order of the child pages in the nav tree. Reverse Nav Order simply reverses that.
 
#set( $containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager') )
#set( $getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null) )
#set( $containerManager=$getInstanceMethod.invoke(null,null) )
#set( $containerContext=$containerManager.containerContext )
#set( $pageManager=$containerContext.getComponent('pageManager') )
 
#set( $data = "" )
#if( $paramOrder == "Nav Order" || $paramOrder == "Reverse Nav order")
	#set( $children =  $pageManager.getPage($content.id).getSortedChildren() )
#elseif( $paramOrder == "Alphabetical" || $paramOrder == "Reverse Alphabetical")
	#set( $array =  $pageManager.getPage($content.id).getChildren() )
	###############################################################
	## Could not find a method to get them in Alphabetical order ##
	## Must sort them myself ... Bubble sort                     ##
	###############################################################
	#set( $size = $array.size() )
	#foreach( $junk in $array )
		#set( $count = -1 )
		#foreach( $line in $array )
			#set( $count = $count + 1 )
			#if( $velocityCount < $size )
				#if( $line.getTitle().compareToIgnoreCase($array.get($velocityCount).getTitle()) > 0 )
					#set( $tmp = $array.get($velocityCount) )
					#set( $junk = $array.set($velocityCount, $line) )
					#set( $junk = $array.set($count, $tmp) )
				#end
			#end
		#end
	#end
	#set( $children = $array)
#elseif( $paramOrder == "Create Date" || $paramOrder == "Reverse Create Date")
	#set( $children =  $pageManager.getPage($content.id).getChildren() )
#end
 
#foreach( $child in $children )
	#set( $include = "" )
	#set( $include = $include + '<div class="included-child-page">')
	#if( $paramShowTitle == true )
		#if( $paramLinkTitle == true )
			#set( $include = $include + '<h1 class="included-child-page-title"><a href="' + $child.getUrlPath() + '">' + $child.getTitle() + '</a></h1>' )
		#else
			#set( $include = $include + '<h1 class="included-child-page-title">' + $child.getTitle() + '</h1>')
		#end
	#end
	#set( $include = $include + '<div class="included-child-page-body">')
		#set( $include = $include + '<ac:structured-macro ac:name="include">')
			#set( $include = $include + '<ac:parameter ac:name="">')
				#set( $include = $include + '<ac:link>')
					#set( $include = $include + '<ri:page ri:content-title="' + $child.getTitle() + '" ri:space-key="' + $content.spaceKey + '"/>')
				#set( $include = $include + '</ac:link>')
			#set( $include = $include + '</ac:parameter>')
		#set( $include = $include + '</ac:structured-macro>')
	#set( $include = $include + '</div>')
	#set( $include = $include + '</div>')
	#if( $paramOrder == "Nav Order"  || $paramOrder == "Alphabetical" || $paramOrder == "Create Date" )
		#set( $data = $data + $include )
	#else
		#set( $data = $include + $data)
	#end
#end
 
$data
 
<style type="text/css">
	.included-child-page {margin-bottom: 30px;}
</style>
Davin Studer Community Champion Aug 26, 2015

I finally decided to tackle sorting on this. It's been bugging me for a while, but I just never had the time to get to it. I have edited my answer above to include sorting. It also includes the options to show/hide the title and link/unlink the title added by @Milo Grika. I also threw in some css classes (included-child-page, included-child-page-title, and included-child-page-body) so that it can be styled. included-child-page wraps each included child page. included-child-page-title and included-child-page-body are each child page's title and body.

I'm getting an error: Error rendering macro 'includechildren' : Error occurred rendering template content Though you totally showed me how to get the simple hide/show/link title thing working! Thanks for the lesson.

Davin Studer Community Champion Aug 26, 2015

Hmmm. I've tried it on 5.5.6 and 5.8.6 and it works fine for me on both. I even tried copying and pasting from this post into a new user macro and it works for me. Sure it copied correctly?

The "double-click to select" fouled me; old-school drag select worked. Sorry for the churn. And thanks for the brilliant code!

This widget could not be displayed.

I managed to convert 'page title' into 'link' (line number 11):

## Developed by: Davin Studer
## Date created: 12/4/2014
## @noparams
#set( $containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager') )
#set( $getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null) )
#set( $containerManager=$getInstanceMethod.invoke(null,null) )
#set( $containerContext=$containerManager.containerContext )
#set( $pageManager=$containerContext.getComponent('pageManager') )
     
#foreach($child in $pageManager.getPage($content.id).getSortedChildren())
  <h1><a href=$child.getUrlPath()>$child.getTitle()</a></h1>
  <p>
      <ac:structured-macro ac:name="include">
        <ac:parameter ac:name="">
          <ac:link>
            <ri:page ri:content-title="$child.getTitle()" ri:space-key="$content.spaceKey"/>
          </ac:link>
        </ac:parameter>
      </ac:structured-macro>
  </p>
#end

 

But sorting is still mystery for me. Can anyone help?

This widget could not be displayed.

You could use the children display macro to display all child pages and some fragment of them (excerpts).

If you want to show the whole content of the page, you will have to use the include page macro. Unfortunately, you will have to add an instance of the macro for every page you want to include and there is not a quick way to insert all child pages.

This also sound like something that could be done creating your own user macro. Unfortunately this may be complex.

This widget could not be displayed.
Davin Studer Community Champion Dec 04, 2014

Another option would be to use the Navitabs add-on. It has a macro to create a tab for each child page and put the contents of each child page into the respective tab.

This widget could not be displayed.

@Alejandro Conde Carrillo

'Children display' macro does not display entire excerpt. This will not do.

Using 'include page' can't be automated (unless you know something I don't know)

@Davin Studer

'Nacitabs' add-on will display tabs, you must click on tam to see what is there. This is not the solution sad

This widget could not be displayed.

Hi @Davin Studer

This is looking awesome. Will you be so kind and extent this with two simple (I hope so) options?

  1. reverse sorting option
  2. make 'child title' a link to child page, not just static text

This would be exactly what we need wink

 

This widget could not be displayed.

I'm trying to make the page titles and linkability optional, but my limited programming skills are obviously holding me back.

I've created the parameters:

## @param ShowTitle:title=Show Title|type=boolean|desc=Deselect to remove the title of the child page.|default=true
## @param LinkTitle:title=Link Title|type=boolean|desc=Select to turn the titles of the child pages into links to those pages (Show Title must be selected).|default=false

Which seems to function.

And the conditionals:

#if ( $paramShowTitle && $paramLinkTitle )
        <h1><a href=$child.getUrlPath()>$child.getTitle()</a></h1>
        #elseif ( $paramShowTitle && !$paramLinkTitle )
        <h1>$child.getTitle()</h1>
        #end

But it shows linked titles no matter which, if any, of the checkboxes are selected. (Removing the conditional altogether makes the titles not show, which satisfied my initial need, but options are good.)

 

Where did I go wrong?

This widget could not be displayed.

Hi,

 I am looking for the same. I want to display all child pages with tree structure using user macro, is this possible?

it should like

image2016-9-23 13:9:9.png

Regards,

Siddheshwar

Davin Studer Community Champion Sep 23, 2016

If you just want a tree structure like your screenshot then use the pagetree macro and set the root page to @self.

I want to achieve this by using user macro because i need to change look and feel for the same

Can we change UI of pagetree macro something like

image2016-9-23 18:41:31.png

Ok.  How about something like this? It will give you a "Collapsible" parameter in the macro setup that will surround the included pages with an expand macro if checked.

## Macro Name: include_children
## Visibility:
## Macro Title: Include Children
## Description: This will include the content from from the child pages onto the parent page that this macro is placed on.
## Categories: Confluence content
## Icon URL:
## Documentation URL: https://bitbucket.org/fredclown/confluence-user-macros
## Macro Body Processing: No macro body

##############################
## Template: ##
##############################
## Developed By: Davin Studer
## Date Created: 12/4/2014
## Updated by: Milo Grika
## Added: show/hide title, link/unlink title.
## Updated by: Gregor Mirai
## Date updated: 26/1/2016
## Added: page separator, PDF split page marker options.

## @param ShowTitle:title=Show Title|type=boolean|desc=Deselect to remove the title of the child page.|default=true
## @param LinkTitle:title=Link Title|type=boolean|desc=Select to turn the titles of the child pages into links to those pages (Show Title must be selected).|default=false
## @param PageSeparator:title=Page Separator|type=boolean|desc=Separate pages with horizontal ruler.|default=false
## @param SplitPages:title=Split Pages|type=boolean|desc=Split pages marker for PDF export will be inserted.|default=false
## @param Collapsible:title=Collapsible|type=boolean|desc=Should the included pages be collapsible?|default=false
## @param FilterLabel:title=Filter on Page Label|type=string|desc=Include only subpages with the specified label.
## @param Order:title=Order|type=enum|enumValues=Nav Order,Reverse Nav Order,Alphabetical,Reverse Alphabetical,Create Date,Reverse Create Date|default=nav order|desc=In what order should the child pages be displayed? Nav Order refers to the order of the child pages in the page tree. Reverse Nav Order simply reverses that.

#set( $containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager') )
#set( $getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null) )
#set( $containerManager=$getInstanceMethod.invoke(null,null) )
#set( $containerContext=$containerManager.containerContext )
#set( $pageManager=$containerContext.getComponent('pageManager') )

## Find the array of (sorted) child pages.
#set( $data = "" )
#if( $paramOrder == "Nav Order" || $paramOrder == "Reverse Nav Order" )
#set( $children = $pageManager.getPage($content.id).getSortedChildren() )
#elseif( $paramOrder == "Alphabetical" || $paramOrder == "Reverse Alphabetical" )
#set( $array = $pageManager.getPage($content.id).getChildren() )
###############################################################
## Could not find a method to get them in Alphabetical order ##
## Must sort them myself ... Bubble sort ##
###############################################################
#set( $size = $array.size() )
#foreach( $junk in $array )
#set( $count = -1 )
#foreach( $line in $array )
#set( $count = $count + 1 )
#if( $velocityCount < $size )
#if( $line.getTitle().compareToIgnoreCase($array.get($velocityCount).getTitle()) > 0 )
#set( $tmp = $array.get($velocityCount) )
#set( $junk = $array.set($velocityCount, $line) )
#set( $junk = $array.set($count, $tmp) )
#end
#end
#end
#end
#set( $children = $array )
#elseif( $paramOrder == "Create Date" || $paramOrder == "Reverse Create Date" )
#set( $children = $pageManager.getPage($content.id).getChildren() )
#end

## Prepare children data.
#set( $count = -1 )
#set( $skipped = 0 )
#set( $size = $children.size() )
#foreach( $child in $children )
## Create the map of labels for the page.
#set( $labelsMap = {} )
#foreach( $label in $child.getLabels() )
#set( $dummy = $labelsMap.put($label.toString(), 1) )
#end

## Include all pages (when no filter label is specified) or pages with a specific label.
#if( $paramFilterLabel && !$labelsMap.containsKey($paramFilterLabel) )
#set( $skipped = $skipped + 1)
#else
#set( $count = $count + 1 )
#set( $include = "" )
#if ( $paramCollapsible == true )
#set( $include = $include + '<ac:structured-macro ac:name="expand">' )
#set( $include = $include + '<ac:parameter ac:name="title">' + $child.getTitle() + '</ac:parameter>' )
#set( $include = $include + '<ac:rich-text-body>' )
#set( $include = $include + '<p>' )
#end
#set( $include = $include + '<div class="included-child-page">' )

## Show title and links.
#if( $paramShowTitle == true )
#if( $paramLinkTitle == true )
#set( $include = $include + '<h1 class="included-child-page-title"><a href="' + $child.getUrlPath() + '">' + $child.getTitle() + '</a></h1>' )
#else
#set( $include = $include + '<h1 class="included-child-page-title">' + $child.getTitle() + '</h1>' )
#end
#end

## Include sub page.
#set( $include = $include + '<div class="included-child-page-body">' )
#set( $include = $include + '<ac:structured-macro ac:name="include">' )
#set( $include = $include + '<ac:parameter ac:name="">' )
#set( $include = $include + '<ac:link>' )
#set( $include = $include + '<ri:page ri:content-title="' + $child.getTitle() + '" ri:space-key="' + $content.spaceKey + '"/>' )
#set( $include = $include + '</ac:link>' )
#set( $include = $include + '</ac:parameter>' )
#set( $include = $include + '</ac:structured-macro>' )
#set( $include = $include + '</div>' )
#set( $include = $include + '</div>' )
#if ( $paramCollapsible == true )
#set( $include = $include + '</p>' )
#set( $include = $include + '</ac:rich-text-body>' )
#set( $include = $include + '</ac:structured-macro>' )
#end

## Define sorting order.
#set( $inOrder = false )
#if( $paramOrder == "Nav Order" || $paramOrder == "Alphabetical" || $paramOrder == "Create Date" )
#set( $inOrder = true )
#end

## Find out, whether we are in between pages or not.
#set( $betweenPages = false )
#if( $inOrder == true && $count < $size - $skipped - 1 )
#set( $betweenPages = true )
#elseif( $inOrder == false && $count > 0 && $count < $size - $skipped )
#set( $betweenPages = true )
#end

## Include page separator or include page split marker used for PDF exports.
#if( $betweenPages == true )
#if( $paramPageSeparator == true )
#set( $include = $include + '<hr/><br/>' )
#end
#if( $paramSplitPages == true )
#set( $include = $include + '<div style="page-break-before:always;"></div>' )
#end
#end

## Add page content in order or in reverse order.
#if( $inOrder == true )
#set( $data = $data + $include )
#else
#set( $data = $include + $data)
#end
#end
#end

$data

<style type="text/css">
.included-child-page {
margin-bottom: 30px;
overflow: hidden;
}
</style>

Nice Davin,

Almost similar, just a small change, I want to display child pages instead of Content of that page

image2016-9-26 10:43:42.png

 

Cheers

Sid

@Davin Studer Help!!!!

GREAT!! Work!!! Thanks for sharing!

I'm attempting with very limited coding skills. To add this Macro to a Parent page but need to modify a bit. I only want to show Parent, Child and h1's of the child. And do not want to show any content.  I have played with your code but since my skills are limited I could figure out at remove the display of content.  

Any insight would be greatly appreciated!!!!

I think what you want could be done with built-in macros. Try this.

On you parent page add the "Children Display" macro with the "Excerpt Display" option set to rich content.

Then on your child pages add an Excerpt macro at the top and inside that macro add a Table of Contents macro and set the options of the TOC macro like this ...

  • Outpust Type - list
  • List Style - disc
  • Minimum Heading Level - 1
  • Maximum Heading Level - 1
  • Printable - checked
  • Absolute URL - checked

Then on your child pages simply put in your content. You parent page will show the child pages and their H1's in a tree format. If you don't like the TOC at the top of the child pages let me know and I can tell you how you can hide that, but still show the headings on the parent page.

Davin!!!!!

That looks great!!!!! I need to apply this to another use case but I will let you know!  I also may want to convert this into a user macro. So that our users can just add a macro and not think about what to select.   

Thank you so much!!!!

I'll get back to you tomorrow afternoon

 

Suggest an answer

Log in or Sign up to answer
Community showcase
Posted Monday in Confluence

Why start from scratch? Introducing four new templates for Confluence Cloud

Hi my Community friends!  For those who don't know me, I'm a product marketer on the Confluence Cloud team - nice to meet you! For those of you who do, you know that I've been all up in your Co...

349 views 2 5
Join discussion

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you