Client Controlled Site Navigation
This tutorial will show you how to provide your clients an option to add, edit, and delete items from the site navigation. You can also control how deep nested items are allowed. This can easily be accomplished out of the box with no addons in Craft CMS.
Structure and Fields
First we need to create fields and add them to a structure channel. We need three fields:
- Link to a Site Page - fieldtype Entries using all sources and limited to 1 entry, handle of sitePageLink.
- Off Site Link - fieldtype Plain Text, handle offSiteLink
- Open in New Tab - fieldtype Lightswitch, handle openInNewTab
Next You'll create the structure section and uncheck the option entries in this section have their own URLS. You can also set the maximum depth for navigation here. I've set mine to 2.
Navigation Structure Settings
Navigation Entry Types
Next we create two different entry types for the navigation: one for on site links and one for offsite links. You can do that by going to Settings > Sections finding the Navigation section we just created and go to Edit entry type. Once there create two entry types. One called Internal Link (handle internalLink) and the other Offsite Link (handle offsiteLink). In the field layout be sure to Show the Title Field and add the fields like this:
Link Field Layouts
Template Code
Below you will find the template code that checks whether the link is internal or offsite. If the link is offsite and open in new tab switch is turned on then target="_blank" will be added to the link.
We have also added data-url attributes and are replacing those with class="active" should they match the url of the current page.
{% set navigation %}
{% set pages = craft.entries.section('navigation').level('<='~2) %}
<ul>
{% nav page in pages %}
<li>
{# Check for entry type / get related entry #}
{% if page.type == 'internalLink' %}
{% set linkedEntry = page.sitePageLink.limit(1).first() %}
<a href="{{ linkedEntry.url }}" data-url="{{ linkedEntry.url }}">{{ page.title }}</a>
{% endif %}
{# Check for entry type / get offsiteLinks #}
{% if page.type == 'offsiteLink' %}
<a href="{{ page.offSiteLink }}" data-url="{{ page.offSiteLink }}" {% if page.openInNewTab == '1' %}target="_blank"{% endif %}>{{ page.title }}</a>
{% endif %}
{% ifchildren %}
<ul class="dropdown" style="background:pink">
{% children %}
</ul>
{% endifchildren %}
</li>
{% endnav %}
</ul>
{% endset %}
{# replace data-uri with active class #}
{{ navigation|replace({('data-url="' ~ craft.request.getUrl() ~ '"'): 'class="active"'})|raw }}
Conclusion
Now your client can easily create internal and external links in the site navigation as well as reorder them. Many clients request the option to set navigation themselves even though it rarely changes. Setting this up is simple and will give clients the control they want without allowing them to touch the underlying html.