I have a one-level structure where I am storing a client's projects, with the ability to reorder them by dragging the entries in the structure.

Each project has been designed to have multiple subpages of information available, accessible by clicking on tabs, where each tabbed view shows a subset of the project data.

Ideally, each tab would have its own URL so I can deep-link to the subpages, each served by a different template, but load in the views via ajax when a tab is clicked on. Is it possible to derive multiple child views with distinct templates from a single entry, without having to manually add child tab entries for every project, which I definitely don't want to make the client do?

The alternative would be to load in all the tabs on initial page load, and show and hide them as they're clicked on, and use pushstate to deep link to those tabs, but I'd rather have them as proper server side URLs, I think.

Does anyone know if this is possible?


Disclaimer: I haven't ever used structure, but hopefully the method described below also works for that section type.

You can do this quite easily with URL-segments

Consider a URL like so:



And so on.

The section/entry route will hit your entry template, but you can create a new route


And point it to your subview template.

There, you ask craft for whatever is in URL segment 3 like so:


And display content based on that.

To get the entry you are on currently, just filter on segment 2 like so:

{% for entry in craft.entries.section('section').slug(craft.request.getSegment(2)) %}
    {{ entry }}

{% endfor %}
  • This looks great, thanks. Related to your last code snippet, I reference entry in my outer _layout template to access global data related to an entry. Is there any way to make sure the outer layout uses the entry matched on from the slug?
    – Alex H
    Nov 11 '14 at 14:03
  • I've solved this by defining these instances in a block and overriding the block in the included templates. Thanks again.
    – Alex H
    Nov 11 '14 at 14:42

In addition to using the url segments as megatrond suggested. You can also define 'Entry Types', and use if..then conditionals or switch statements in your template to modify the layout or include different sub-templates, as required.

{% if entry.type == 'project' %}
    {% include '/projects/_tabbed-entry' %}
{% endif %}

Furthermore you can use levels and other heirarchy tools (descendants, ancestors, parent, etc) to dynamically construct navigation and/or tabs, such that, for example, the top 2 or 3 levels can be used for your primary navigation, and subsequent levels can be used to construct tabs or sub-nav on the page.

{# build primary nav #}
{% set navEntries = craft.entries.section('pages').level('<= 2') %}
<ul class="nav__level1">
    {% nav entry in navEntries %}
            <a href="{{ entry.url }}"><span>{{ entry.title }}</span></a>
            {% ifchildren %}
                <ul class="nav__level{{ entry.level + 1 }}">
                    {% children %}
            {% endifchildren %}
    {% endnav %}

And for tabs (which works equally well for subnav):

{# build tabs #}
{% set tabEntries = entry.parent.descendants(1) %}
<ul class="tabs">
    {% for tabEntry in tabEntries %}
        <li class="tab" >
            <a href="{{ tabEntry.url }}" {% if tabEntry.id == entry.id %}class="selected"{% endif %} >{{ tabEntry.title }}</a>
    {% endfor %}

<div class="page-content">
    {{ entry.body }}

The examples above will link to each sub-page/tab as a unique url. However, if you want to load the tab content via ajax then you can specify which part of the template is returned in the ajax request, using craft.request.isAjax. This would allow you to essentially load the template into itself if you wanted:

{% if craft.request.isAjax %}
    {# return only the content #}
{% else %}
    {# return the full page with header, nav, content, etc. #}
{% endif %}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.