WordPress Tutorial – Table of Contents in a Page

This tutorial will explain how to add a table of contents to a generic WordPress page. Our table of contents will be a list of posts in chronological order. This tutorial is a follow up to a comment on the post for my WordPress Table of Contents Widget by Ashley who indicated that she would be interested in the capability of having a table of contents in a page rather then the sidebar.

WordPress has the wonderful capability of allowing specific pages to have custom templates. In the initial version of Muse’s Success, we exploited this capability along with custom fields to generate the listing directory and listing detail pages.

Firstly, I would like you to make a copy of your default pages template. This file is usually named page.php, and located in /wp-content/themes/[name of your theme]/ directory of WordPress installation. Name this copy, table_of_contents.php, and open it in your favourite text editor.

Add the following to line 1 of your table_of_contents.php. It needs to be the first thing in your file.

1
2
<?php /* Template Name: Table of Contents
*/ ?>

Find:

1
<?php the_content('<p class="serif">Read the rest of this page &raquo;</p>'); ?>

This line may be slightly different, your basically looking for an instance of <?php the_content(‘…’). ?> Don’t worry about what the single parameter, if any.

Immediately after add:

This is the basic code to output post titles in chronological order. You can make slight variations of this, and it in general depends on how you’ve been naming your posts. In my experience, most authors are placing the chapter number and title in their WordPress post titles, so this example is geared towards these authors, but I will show some alternatives at the end of this tutorial.

1
2
3
4
5
6
7
8
9
<?php
global $post;
$post_save = $post;
$category_id = get_post_meta($post->ID, 'toc_category_id', true);
$toc = get_posts('numberposts=-1&category='.$category_id.'&order=ASC&orderby=date');
foreach($toc as $post) :
?>
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a><br />
<?php endforeach; $post = $post_save; ?>

Create the Page

Now, we have to create a WordPress page. You can do this by selecting Pages -> Add New in your WordPress Dashboard Menu. It’s up to you what you name your page, and what you write in the content area, but I would recommend the title is that of your book, and your content area contains a short introduction to your story (like what you would have on the blurb of a print book).

Select the Custom Template

Before you publish your page, we have a few special things we need to do to make the table of contents appear. You’ll need to select the Table of Contents template in the Attributes section (lower right) of the Add Page page as depicted.

Attributes

Set the Custom Field

Next, we have to add a custom field. Custom fields can be added below the page content area. Name your custom field “toc_category_id” and set the value to the ID number of the category containing your posts. You can find the ID out by going to the Edit Categories (Dashboard menu -> Posts -> Categories) page, and clicking Edit under the category containing the posts that comprise your story. On the Edit Category page, take a look at your address bar, and you’ll see the text &cat_ID=. The number after the equals sign is your category ID.

custom_field

Click Add Custom Field, and then Publish, and you’re done. If all went well, when you view the page you just created, you should see your new table of contents.

Using an ordered list instead

Earlier, I mentioned that there are other variations of the code that are suited to different post naming schemes. The one I showed earlier was a basic one title after another list using linebreaks.

If you are one who names their posts solely the name of your chapter with no number, you might like to use an ordered list to automatically add the chapter number for you.

1
2
3
4
5
6
7
8
9
10
11
<ol>
<?php
global $post;
$post_save = $post;
$category_id = get_post_meta($post->ID, 'toc_category_id', true);
$toc = get_posts('numberposts=-1&category='.$category_id.'&order=ASC&orderby=date');
foreach($toc as $post) :
?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endforeach; $post = $post_save; ?>
</ol>

Those knowing CSS (and respecting semantics) but naming their chapters with number and name might also want to use the above code, but use CSS to hide the numbers in visual browsers.

Posted September 23rd, 2009 in Code, Tutorials, WordPress

  • TL;DR version:

    1. Copy page.php template.
    2. Rename copy table_of_contents.php
    3. Make the edit I suggest in the main article.
    4. Save template / upload
    5. Create New Page
    6. Fill in title and content
    7. Select the Table of Contents custom template under Attributes.
    8. Add a custom field named "toc_category_id" with the value being the ID of the category containing your chapters.
    9. Publish
    10. Enjoy your new table of contents page.
  • It's not too complicated. My PHP knowledge is virtually nill nowadays (I haven't done much programming in two years or so), but I think I can get this going ;) I didn't even think of using a custom page template : D
  • I'm glad. Let me know if you get it work, please.
  • I'm sure it's something simple like, "oh, you've got an extra apostrophe" or something, but it seems to be displaying every post, instead of just the posts from category ID "4".

    http://heiwuya.net/serial-fiction/the-crow/tabl... Is the page in question, and I've got screenshots of all the applicable code (I hope)

    http://img59.imageshack.us/img59/3285/editcateg...
    http://img185.imageshack.us/img185/4083/editthe...
    http://img32.imageshack.us/img32/897/tableofcon...

    I also double-checked it against the WP Codex, and tried hard-coding the value for the category in there. It seems fine to me, and I tried copy & pasting the example from the Codex, to no avail.
  • I'm sorry for the late reply. WordPress marked the message as spam due the number of links. Looking at your site, it appears you fixed it, but I'll go over a solution here.

    Try this (I haven't tried it, but I think it should work):

    http://php.pastebin.com/f53118d4e

    Good luck. If this works, I'll replace the code in the tutorial with it.
  • My apologies, WordPress seems to have killed my comment.

    Code:
    http://php.pastebin.com/f9be2b8e
  • My fix was to replace category() with category_name().

    Your new code results in a blank page (my server seems to have turned off PHP errors). But the initial problem seems to be my installation. It seems to think every post is in category 4 (even when navigating in the WP control panel).
  • That's weird. I tried it just now and it worked as expected. I know pastebin tends to add #'s when you copy and paste sometimes, did you remove those?

    I'm not sure about this WordPress category issue but I believe I had a similar issue when making the sidebar widget table of contents. No matter what I set the category to it was always getting the wrong posts. The solution was the same as the solution I used in the new code - using the database table field names directly instead of relying on WordPress's template functions for the title and permalink.
  • Fixed it, it ended up being a problem with the actual database itself. A wipe of the database and a re-installation solved the problem, and both the first and second code snippets work perfectly now.

    I have no idea what could have caused the database to screw itself up so royally, but that was the problem, not your code! Sorry for the mix-up, and thanks a lot for the help!
  • Okay, I finally got a plugin that allows me to assign categories to my pages, and while the plugin is working for POSTS, it's not working for pages. I have used the code displayed exactly the way it is shown here (with the only modification being that I replaced OL with UL for asthetics) and it's not working.

    Is there something I'm doing wrong? This is a site I'm transferring into Wordpress, so it can blow up and I won't be TOO mad...
  • The plugin and table of contents described in this tutorial doesn't support pages.

    I haven't tested but I think replacing $toc = get_post... with $toc = get_pages('child_of='.$post->ID.'&sort_column=post_date&sort_order=ASC'); should do the trick. Of course, replace '.$post->ID.' with the ID of the page that is the parent of the chapters you want to list if it isn't the page that holds the parent (even so you might still need to replace it, I don't know).

    Good luck.
  • Sir, you saved my backside. Changing the code like you mention fixes it for pages, but you do have to get a plugin to allow you to assign categories to your pages. With those two (plugin + your hack) I have now got index pages for a specific sub category.

    Oh, the plugin I used so that others can use it is located here: http://www.megaupload.com/?d=CLBDY6U0

    I downloaded that, implemented it, created categories, assigned them to pages and then, with that code change: http://davensjournal.com/Updating/beginning-wicca

    I'm VERY happy now.
blog comments powered by Disqus