Multi-level Bootstrap 4 Navbar With Craft 3 (No Plugins)
Problem
You want to setup a Bootstrap 4 Navbar and use native functions in Craft 3 to manage the navigation menu.
Solution
This was built for Bootstrap v4.0 and Craft CMS 3.0.0-RC9
Step 1: Install Craft 3
Go to https://github.com/craftcms/docs/blob/v3/en/installation.md and install Craft 3.
Step 2: Download and Install latest Bootstrap 4 build
Currently v4.0 which you can get at https://getbootstrap.com.
Step 3: Build Navigation in Craft 3 using a Structure 2 Level Section
Setup your 2 level Structure section for navigation in Craft 3. Call the section Navigation so the handle is navigation
.
Setup four fields as follows:
Name: Link to a Site Asset
- Handle: siteAssetLink
- Instructions: Use this link type to link to any uploaded Asset on your site (PDFs, documents, images, etc.)
- Field Type: Assets
- Sources: All
- Limit: 1
Name: Link to a Site Page
- Handle: sitePageLink
- Instructions: Use this link type to link to any other Page or Entry on your site
- Field Type: Entries
- Sources: All
- Limit: 1
- Selection Label: Add a Page
Name: Offsite Link
- Handle: offsiteLink
- Instructions: Use this link type to link to any URL outside of your website. Enter the full URL you would like to link * to including the http://
- Field Type: URL
Name: Open In New Window
- Handle: openInNewWindow
- Instructions: Toggle this switch to Open this Link in a new browser tab or window
- Field Type: Lightswitch
- Default Value: off
Setup three Entry Types as follows in your Navigation Structure section:
Name: Internal Site Link
- Handle: internalSiteLink
- Show the Title Field: checked
- Title Field Label: Title
- Fields: Link to a Site Page
Name: Internal Asset Link
- Handle: internalAssetLink
- Show the Title Field: checked
- Title Field Label: Title
- Fields: Link to a Site Asset, Open in New Window
Name: Offsite Link
- Handle: offsiteLink
- Show the Title Field: checked
- Title Field Label: Title
- Fields: Offsite Link, Open in New Window
Step 4: Code it out
Setup your template code as follows:
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="{{ siteUrl }}">{{ siteName }}</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
{% set navigation = craft.entries.section('navigation') %}
<ul class="navbar-nav mr-auto">
{% nav node in navigation.level(1).all() %}
{% if node.hasDescendants() %}
<li class="nav-item dropdown">
{% if node.type == 'internalSiteLink' %}
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown{{ node.id }}" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ node.title }}</a>
{% elseif node.type == 'internalAssetLink' %}
{% set asset = node.siteAssetLink.one() %}
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown{{ node.id }}" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ node.title }}</a>
{% elseif node.type == 'offsiteLink' %}
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown{{ node.id }}" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ node.title }}</a>
{% endif %}
<div class="dropdown-menu" aria-labelledby="navbarDropdown{{ node.id }}">
{% set nodeSubs = node.getChildren() %}
{% for nodeSub in nodeSubs.all() %}
{% if nodeSub.type == 'internalSiteLink' %}
<a class="dropdown-item" href="{{ nodeSub.sitePageLink[0].url }}">{{ nodeSub.title }}</a>
{% elseif nodeSub.type == 'internalAssetLink' %}
{% set asset = nodeSub.siteAssetLink.one() %}
<a class="dropdown-item" href="{{ asset.url }}" {% if nodeSub.openInNewWindow %} target="_blank" {% endif %}>{{ nodeSub.title }}</a>
{% elseif node.type == 'offsiteLink' %}
<a class="dropdown-item" href="{{ nodeSub.offsiteLink }}" {% if nodeSub.openInNewWindow %} target="_blank" {% endif %}>{{ nodeSub.title }}</a>
{% endif %}
{% endfor %}
</div>
</li>
{% else %}
<li class="nav-item">
{% if node.type == 'internalSiteLink' %}
<a class="nav-link" href="{{ node.sitePageLink[0].url }}">{{ node.title }}</a>
{% elseif node.type == 'internalAssetLink' %}
{% set asset = node.siteAssetLink.one() %}
<a class="nav-link" href="{{ asset.url }}" {% if node.openInNewWindow %} target="_blank" {% endif %}>{{ node.title }}</a>
{% elseif node.type == 'offsiteLink' %}
<a class="nav-link" href="{{ node.offsiteLink }}" {% if node.openInNewWindow %} target="_blank" {% endif %}>{{ node.title }}</a>
{% endif %}
</li>
{% endif %}
{% endnav %}
</ul>
</div><!--/.navbar-collapse -->
</nav>
As new Bootstrap 4 and Craft 3 releases come out you may need to tweak the code. Just watch their changelogs for any changes.
Submitted by Bryan Garrant on 9th February, 2018