Adding multi-level menu's with Timber - wordpress

I am not familiar with Timber - in-fact this is the first time I've ever heard of it, but I'm helping a charity out who's web developer have left them in the lurch.
I've worked most things out - except getting sub-menu's working.
When items are added to the sub-menu location in Wordpress, they are appearing on the same level on the main menu.
Was wondering if someone could help me out?
Code is below for the various "twigs" - but let me know if you need the functions code as well to help out.
menu.twig:
{% for item in menu %}
<li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
<a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
{% include "menu.twig" with {'menu': item.get_children} %}
</li>
{% endfor %}
{% endif %}
header.twig
<header class="header">
<div class="header__secondary">
<div class="container">
<div class="row">
<div class="col-xs-12">
<nav class="header__nav nav-secondary">
<ul class="nav-secondary__ul">
{% include "menu.twig" with {
'menu': menu.header_secondary.items,
'prefix': 'nav-secondary'
} %}
<li class="nav-secondary__li nav-secondary__li--cart">
<a class="nav-secondary__a cart-customlocation" href="{{ cart_url }}"></a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div class="header__primary">
{% block header %}
<div class="container">
<div class="row">
<div class="col-xs-6 col-md-2">
<a href="/" class="header__logo">
<img src="{{ site.theme.link }}/dist/img/logo.jpg" alt="{{ site.name }} Logo">
</a>
</div>
<div class="col-xs-6 col-md-10">
<nav class="header__nav nav" role="navigation">
<ul class="nav__ul">
{% include "menu.twig" with {
'menu': menu.header_primary.items,
'prefix': 'nav'
} %}
</ul>
</nav>
<div class="hamburger hamburger--spring">
<div class="hamburger-box">
<div class="hamburger-inner"></div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
</div>
</header>
functions.php
<?php
/**
* Timber starter-theme
* https://github.com/timber/starter-theme
*
* #package WordPress
* #subpackage Timber
* #since Timber 0.1
*/
if ( ! class_exists( 'Timber' ) ) {
add_action( 'admin_notices', function() {
echo '<div class="error"><p>Timber not activated. Make sure you activate the plugin in ' . esc_url( admin_url( 'plugins.php' ) ) . '</p></div>';
});
add_filter('template_include', function( $template ) {
return get_stylesheet_directory() . '/static/no-timber.html';
});
return;
}
Timber::$dirname = array('views');
Timber::$autoescape = false;
/**
* We're going to configure our theme inside of a subclass of Timber\Site
* You can move this to its own file and include here via php's include("MySite.php")
*/
class StarterSite extends Timber\Site {
/** Add timber support. */
public function __construct() {
add_action( 'after_setup_theme', array( $this, 'theme_supports' ) );
add_filter( 'timber_context', array( $this, 'add_to_context' ) );
add_filter( 'get_twig', array( $this, 'add_to_twig' ) );
add_action( 'init', array( $this, 'register_post_types' ) );
add_action( 'init', array( $this, 'register_taxonomies' ) );
add_action( 'wp_enqueue_scripts', [$this, 'load_scripts'] );
parent::__construct();
register_nav_menu('header-secondary', 'Header Secondary');
register_nav_menu('header-primary', 'Header Primary');
remove_action('woocommerce_before_main_content', 'woocommerce_breadcrumb', 20, 0); // kill woo breadcrumbs
remove_action( 'woocommerce_before_shop_loop' , 'woocommerce_catalog_ordering', 30 ); // kill woo sorting
remove_action( 'woocommerce_before_shop_loop' , 'woocommerce_result_count', 20 ); // kill woo # results
add_filter( 'woocommerce_add_to_cart_fragments', [$this, 'woocommerce_header_add_to_cart_fragment']);
add_filter( 'woocommerce_get_image_size_gallery_thumbnail', function( $size ) {
return array(
'width' => 400,
'height' => 400,
'crop' => 0,
);
});
add_action( 'after_setup_theme', function() {
add_theme_support( 'woocommerce' );
} );
}
/** This is where you can register custom post types. */
public function register_post_types() {
$name = "adoption";
$singular = "Adoption";
$plural = "Adoptions";
$labels = array(
'name' => _x("$plural", 'en'),
'singular_name' => _x("$singular", 'en'),
'all_items' => "All $plural",
'add_new' => _x("Add New $singular", 'en'),
'add_new_item' => _x("Add New $singular", 'en'),
'edit_item' => _x("Edit $singular", 'en'),
'new_item' => _x("New $singular", 'en'),
'view_item' => _x("View $singular", 'en'),
'search_items' => _x("Search $plural", 'en'),
'not_found' => _x("No $singular found", 'en'),
'not_found_in_trash' => _x("No $singular found in Trash", 'en'),
'parent_item_colon' => _x("Parent $singular:", 'en'),
'menu_name' => _x("$plural", 'en'),
);
$args = array(
'labels' => $labels,
'hierarchical' => false,
'description' => $plural,
'supports' => array(
'title',
'editor',
'thumbnail',
'revisions'
),
'taxonomies' => ['adoption_type'],
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 4,
'menu_icon' => 'dashicons-welcome-view-site',
'show_in_nav_menus' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite' => true,
'capability_type' => 'post'
);
register_post_type($name, $args);
$name = "event";
$singular = "Event";
$plural = "Events";
$labels = array(
'name' => _x("$plural", 'en'),
'singular_name' => _x("$singular", 'en'),
'all_items' => "All $plural",
'add_new' => _x("Add New $singular", 'en'),
'add_new_item' => _x("Add New $singular", 'en'),
'edit_item' => _x("Edit $singular", 'en'),
'new_item' => _x("New $singular", 'en'),
'view_item' => _x("View $singular", 'en'),
'search_items' => _x("Search $plural", 'en'),
'not_found' => _x("No $singular found", 'en'),
'not_found_in_trash' => _x("No $singular found in Trash", 'en'),
'parent_item_colon' => _x("Parent $singular:", 'en'),
'menu_name' => _x("$plural", 'en'),
);
$args = array(
'labels' => $labels,
'hierarchical' => false,
'description' => $plural,
'supports' => array(
'title',
'editor',
'thumbnail',
'revisions'
),
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 4,
'menu_icon' => 'dashicons-welcome-view-site',
'show_in_nav_menus' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite' => true,
'capability_type' => 'post'
);
register_post_type($name, $args);
if(function_exists('acf_add_options_page')) {
acf_add_options_page([
'page_title' => 'Theme Content',
'menu_title' => 'Theme Content',
'menu_slug' => 'theme-content',
'capability' => 'edit_posts',
'redirect' => false
]);
}
if(function_exists('acf_add_options_page')) {
acf_add_options_page([
'page_title' => 'Donation Settings',
'menu_title' => 'Donation Settings',
'menu_slug' => 'donation-settings',
'capability' => 'edit_posts',
'redirect' => false
]);
}
}
/** This is where you can register custom taxonomies. */
public function register_taxonomies() {
$labels = array(
'name' => 'Adoption Types',
'singular_name' => 'Adoption Type',
'menu_name' => 'Adoption Type'
);
$rewrite = array(
'slug' => 'adoptions',
'with_front' => true,
'hierarchical' => false,
);
$args = array(
'labels' => $labels,
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_admin_column' => true,
'show_in_nav_menus' => true,
'show_tagcloud' => false,
'rewrite' => $rewrite,
);
register_taxonomy( 'adoption_type', 'adoption', $args );
}
public function load_scripts() {
wp_enqueue_style( 'main', get_stylesheet_directory_uri() . '/dist/css/main.min.css' );
wp_enqueue_script('slick-js', get_stylesheet_directory_uri() . '/dist/js/plugins/slick.min.js', 'jquery', false, true);
wp_enqueue_script('main-js', get_stylesheet_directory_uri() . '/dist/js/main.js', ['jquery', 'slick-js'], false, true);
}
/** This is where you add some context
*
* #param string $context context['this'] Being the Twig's {{ this }}.
*/
public function add_to_context( $context ) {
$context['options'] = get_fields('options');
$context['menu']['header_primary'] = new Timber\Menu('header-primary');
$context['menu']['header_secondary'] = new Timber\Menu('header-secondary');
$context['shop_url'] = get_permalink(woocommerce_get_page_id('shop' ));
$context['site'] = $this;
if (get_the_ID()) {
// load page modules
require_once('src/modules.php');
}
return $context;
}
public function theme_supports() {
// Add default posts and comments RSS feed links to head.
add_theme_support( 'automatic-feed-links' );
/*
* Let WordPress manage the document title.
* By adding theme support, we declare that this theme does not use a
* hard-coded <title> tag in the document head, and expect WordPress to
* provide it for us.
*/
add_theme_support( 'title-tag' );
/*
* Enable support for Post Thumbnails on posts and pages.
*
* #link https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/
*/
add_theme_support( 'post-thumbnails' );
/*
* Switch default core markup for search form, comment form, and comments
* to output valid HTML5.
*/
add_theme_support(
'html5', array(
'comment-form',
'comment-list',
'gallery',
'caption',
)
);
/*
* Enable support for Post Formats.
*
* See: https://codex.wordpress.org/Post_Formats
*/
add_theme_support(
'post-formats', array(
'aside',
'image',
'video',
'quote',
'link',
'gallery',
'audio',
)
);
add_theme_support( 'menus' );
}
/** This Would return 'foo bar!'.
*
* #param string $text being 'foo', then returned 'foo bar!'.
*/
public function myfoo( $text ) {
$text .= ' bar!';
return $text;
}
/** This is where you can add your own functions to twig.
*
* #param string $twig get extension.
*/
public function add_to_twig( $twig ) {
$twig->addExtension( new Twig_Extension_StringLoader() );
$twig->addFilter( new Twig_SimpleFilter( 'myfoo', array( $this, 'myfoo' ) ) );
return $twig;
}
function woocommerce_header_add_to_cart_fragment( $fragments ) {
global $woocommerce;
ob_start();
?>
<a class="cart-customlocation" href="<?php echo $woocommerce->cart->get_cart_url(); ?>" title="<?php _e('View your shopping cart', 'woothemes'); ?>"><?php echo sprintf(_n('%d item', '%d items', $woocommerce->cart->cart_contents_count, 'woothemes'), $woocommerce->cart->cart_contents_count);?> - <?php echo $woocommerce->cart->get_cart_total(); ?></a>
<?php
$fragments['a.cart-customlocation'] = ob_get_clean();
return $fragments;
}
}
new StarterSite();
EDIT: Based on feedback received, the menu.twig code is as follows - however, not showing any menus now:
{% if items|default(menu.items) %}
<ul>
{% for item in items|default(menu.items) %}
<li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
<a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
{% include "menu.twig" with {'menu': item.get_children} %}
</li>
{% endfor %}
</ul>
{% endif %}
EDIT 2: Below is header.twig as there's some more menu stuff in there...
<header class="header">
<div class="header__secondary">
<div class="container">
<div class="row">
<div class="col-xs-12">
<nav class="header__nav nav-secondary">
<ul class="nav-secondary__ul">
{% include "menu.twig" with {
'menu': menu.menu_header_secondary.items,
'prefix': 'nav-secondary'
} %}
<li class="nav-secondary__li nav-secondary__li--cart">
<a class="nav-secondary__a cart-customlocation" href="{{ cart_url }}"></a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div class="header__primary">
{% block header %}
<div class="container">
<div class="row">
<div class="col-xs-6 col-md-2">
<a href="/" class="header__logo">
<img src="{{ site.theme.link }}/dist/img/logo.jpg" alt="{{ site.name }} Logo">
</a>
</div>
<div class="col-xs-6 col-md-10">
<nav class="header__nav nav" role="navigation">
<ul class="nav__ul">
{% include "menu.twig" with {
'menu': menu.menu_header_primary.items,
'prefix': 'nav'
} %}
</ul>
</nav>
<div class="hamburger hamburger--spring">
<div class="hamburger-box">
<div class="hamburger-inner"></div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
</div>
</header>
EDIT 3 - current config after #Gchtr input and getting the correct menus to display in the correct locations. Still no sub-menus:
menu.twig:
{% set items = items|default(menu.items) %}
{% if items %}
<ul>
{% for item in items %}
<li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
<a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
{% if item.children %}
{% include "menu.twig" with { items: item.children } %}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
header.twig:
<header class="header">
<div class="header__secondary">
<div class="container">
<div class="row">
<div class="col-xs-12">
<nav class="header__nav nav-secondary">
<ul class="nav-secondary__ul">
{% include "menu.twig" with {
'menu': menu_header_secondary,
'prefix': 'nav-secondary'
} %}
<li class="nav-secondary__li nav-secondary__li--cart">
<a class="nav-secondary__a cart-customlocation" href="{{ cart_url }}"></a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div class="header__primary">
{% block header %}
<div class="container">
<div class="row">
<div class="col-xs-6 col-md-2">
<a href="/" class="header__logo">
<img src="{{ site.theme.link }}/dist/img/logo.jpg" alt="{{ site.name }} Logo">
</a>
</div>
<div class="col-xs-6 col-md-10">
<nav class="header__nav nav" role="navigation">
<ul class="nav__ul">
{% include "menu.twig" with {
'menu': menu_header_primary,
'prefix': 'nav'
} %}
</ul>
</nav>
<div class="hamburger hamburger--spring">
<div class="hamburger-box">
<div class="hamburger-inner"></div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
</div>
</header>
functions.php (snippet of the Header Stuff instead of the whole lot):
public function add_to_context( $context ) {
$context['options'] = get_fields('options');
$context['menu_header_primary'] = new Timber\Menu( 'header-primary' );
$context['menu_header_secondary'] = new Timber\Menu( 'header-secondary') ;
$context['shop_url'] = get_permalink(woocommerce_get_page_id('shop' ));
$context['site'] = $this;

In your StarterSite class in the add_to_context() method, you’re adding your menus like so:
$context['menu']['header_primary'] = new Timber\Menu('header-primary');
$context['menu']['header_secondary'] = new Timber\Menu('header-secondary');
When you now want to use access menu.items in your Twig, that doesn’t work, because you don’t access the nested value. It should be menu.header_primary.items. To simplify this, I’d change that to use separate context entries:
$context['menu_header_primary'] = new Timber\Menu( 'header-primary' );
$context['menu_header_secondary'] = new Timber\Menu( 'header-secondary') ;
Then, for your Twig file, you’ll always need to pass a menu variable.
{% set items = items|default(menu.items) %}
{% if items %}
<ul>
{% for item in items %}
<li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
<a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
{% if item.children %}
{% include "menu.twig" with { items: item.children } %}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
Edit
In your header.twig, you’ll need to remove the nesting from menu include as well (menu_header_primary.items instead of menu.menu_header_primary.items. Otherwise, Timber will the take the first menu it can find.
<nav class="header__nav nav" role="navigation">
<ul class="nav__ul">
{% include "menu.twig" with {
menu: menu_header_primary,
prefix: 'nav'
} %}
</ul>
</nav>

Function.php
/**
* Regsiter Nav Menus
*/
public function theme_register_nav_menus() {
register_nav_menus( array(
'primary_menu' => esc_html__( 'Primary Menu', 'themenamehere' ),
'secondary_menu' => esc_html__( 'Secondary Menu', 'themenamehere' ),
) );
}
/** This is where you add some context
*
* #param string $context context['this'] Being the Twig's {{ this }}.
*/
public function add_to_context( $context ) {
$context['menu'] = new Timber\Menu();
$context['secondaryMenu'] = new Timber\Menu('secondary_menu');
$context['site'] = $this;
return $context;
}
Menu.twig
{% if menu %}
<ul>
{% for item in items %}
<li class="{{ item.classes | join(' ')}}">
{# <a target="{{ item.target}}" href="{{ item.link}}">{{ item.title}}</a> #}
<a target="_self" href="{{ item.link}}">{{ item.title}}</a>
{% include "menu.twig" with{'items':item.children} %}
</li>
{% endfor %}
</ul>
{% endif %}
After that include that file inside Twig file bascically in base.twig file:
For Primary Menu Code looks like:
{% include "menu.twig" with{'items':menu.get_items} %}
For Secondary Menu Code looks like:
{% include "menu.twig" with{'items':secondaryMenu.get_items} %}

it looks like you are missing <ul></ul> wrapper or you haven't posted the code in the entire:
{% if menu %}
<ul>
{% for item in menu %}
<li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
<a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}">{{ item.title }}</a>
{% include "menu.twig" with {'items': item.children} %}
</li>
{% endfor %}
</ul>
{% endif %}

Related

Use FormTheme for CollectionType?

I'm using for my symfony project the Ninsuo JqueryCollection plugin https://symfony-collection.fuz.org/symfony3/, and I have a form that has a collectionType, except that I want the targeted entity to appear with its own layout, but I do not know how to apply it to CollectionType
I have my "subform" like this
SubForm :
{{form_start(form)}}
<div class="card">
<h5 class="card-header">Nouvel utilisateur</h5>
<div class="card-body">
{{form_row(form.email)}}
<div class="row align-items-center">
<div class="col-md-4">
{{form_row(form.nom)}}
</div>
<div class="col-md-4">
{{form_row(form.prenom)}}
</div>
<div class="col-md-4">
{{form_row(form.service)}}
</div>
</div>
{{form_row(form.roles)}}
</div>
</div>
{{form_end(form)}}
And my main Form :
{{form_start(form)}}
{{form_row(form.utilisateurs, {'attr': {'class': 'my-selector jquery-buttons-collection mt-3'} })}}
<button type="submit" class="btn btn-primary">Enregistrer</button>
{{form_end(form)}}
I would like to apply the layout of the 1st form for my form.users. Someone would know how?
EDIT:
My main form :
$builder
->add('utilisateurs', CollectionType::class, [
'entry_type' => AdminUserRegistrationType::class,
'entry_options' => [
'label' => false,
],
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => true,
'by_reference' => true,
'prototype' => true,
'label' => false,
'attr' => array(
'class' => 'my-selector',
'label' => false,
),
'by_reference' => false,
]);
;
With the template :
{{form_start(form)}}
{{form_row(form.utilisateurs, {'attr': {'class': 'my-selector jquery-buttons-collection mt-3'} })}}
<button type="submit" class="btn btn-primary">Enregistrer</button>
{{form_end(form)}}
The form.utilisateurs formType :
$builder
->add('nom', TextType::class)
->add('prenom', TextType::class)
->add('email', EmailType::class)
->add('service', EntityType::class, [
'class' => GroupeValidateurs::class,
'query_builder' => function (GroupeValidateursRepository $repo) {
return $repo->createQueryBuilder("g")
->orderBy("g.nom", 'ASC');
},
'choice_label' => 'nom',
'label' => "Service",
'placeholder' => 'Service'
])
->add('roles', ChoiceType::class, [
'label' => "Rôles",
'choices' => [
'Admin' => 'ROLE_ADMIN',
'Direction' => 'ROLE_DIRECTION',
'RH' => 'ROLE_RH',
],
"expanded" => true,
"multiple" => true,
])
;
And the form theme :
{% block utilisateursType_label %}{% endblock %}
{% block utilisateursType_errors %}{% endblock %}
{% block utilisateursType_widget %}
<div class="card">
<h5 class="card-header">Nouvel utilisateur</h5>
<div class="card-body">
{{form_widget(form.email)}}
<div class="row align-items-center">
<div class="col-md-4">
{{form_widget(form.nom)}}
</div>
<div class="col-md-4">
{{form_widget(form.prenom)}}
</div>
<div class="col-md-4">
{{form_widget(form.service)}}
</div>
</div>
{{form_widget(form.roles)}}
</div>
</div>
{% endblock %}
But I don't know how find the block name

Dropdown Menus with KnpMenuBundle and Bootstrap 3

I've just added the KnpMenuBundle to my Symfony project.
I also added Bootstrap to make it look nicer.
Now I want to create a Submenu or Dropdownmenu.
Is there a simple example / way how to do this?
I've searched a lot of examples but either they require an additional bundle or do not work
Update
I need to know how I have to add attributes to my menu children in order to render it with bootstrap
Best regards
Oliver
It's rather straightforward. For attributes, see the KnpMenu docs.
An example:
base.html.twig, which appears in templates with {% extends "base.html.twig" %}:
...
{% block stylesheets %}
<link href="{{ asset('css/bootstrap.css') }}" rel="stylesheet" media="all">
<link href="{{ asset('css/pdf.css') }}" rel="stylesheet" media="all">
<link href="{{ asset('css/jquery-ui.min.css') }}" rel="stylesheet" media="all" />
{% endblock %}
...
{% block nav %}
{% spaceless %}
<nav class="navbar navbar-default">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#"></a>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
{{ knp_menu_render('AppBundle:Builder:mainMenu', {'style': 'navbar'}) }}
{{ knp_menu_render('AppBundle:Builder:logoutMenu', { 'style': 'navbar-right' }) }}
</div>
</nav>
{% endspaceless %}
{% endblock nav %}
...
{% block javascripts %}
<script
src="https://code.jquery.com/jquery-1.11.3.js"
integrity="sha256-IGWuzKD7mwVnNY01LtXxq3L84Tm/RJtNCYBfXZw3Je0="
crossorigin="anonymous"></script>
<script src="{{ asset('js/bootstrap.js') }}"></script>
<script src="{{ asset('js/jquery-ui.min.js') }}"></script>
<script src="{{ asset('js/project.js') }}"></script>
{% endblock %}
Builder.php:
...
class Builder implements ContainerAwareInterface
{
use ContainerAwareTrait;
public function mainMenu(FactoryInterface $factory, array $options)
{
$checker = $this->container->get('security.authorization_checker');
$menu = $factory->createItem('root');
$menu->addChild('Home', array('route' => 'homepage'));
$menu->addChild('Receipt');
$menu['Receipt']->addChild('Add receipt', [
'route' => 'receipt_add'
]);
$menu['Receipt']->addChild('Edit receipt', [
'route' => 'receipt_edit'
]);
$menu->addChild('Artist');
$menu['Artist']->addChild('Add artist', [
'route' => 'artist_add'
]);
$menu['Artist']->addChild('Edit artist', [
'route' => 'artist_edit'
]);
$menu['Artist']->addChild('Add existing to show', [
'route' => 'existing_artists'
]);
$menu->addChild('Tickets');
$menu['Tickets']->addChild('Add block', [
'route' => 'block_add'
]);
$menu['Tickets']->addChild('Edit block', [
'route' => 'block_edit'
]);
$menu->addChild('Show');
$menu['Show']->addChild('Add show', [
'route' => 'show_add'
]);
$menu['Show']->addChild('Edit show', [
'route' => 'show_edit'
]);
$menu->addChild('Reports', [
'route' => 'reports'
]);
if ($checker->isGranted('ROLE_ADMIN')) {
$menu->addChild('Admin');
$menu['Admin']->addChild('Ticket block reassign', [
'route' => 'block_reassign'
]);
$menu['Admin']->addChild('Users', [
'route' => 'easyadmin'
]);
$menu['Admin']->addChild('Delete artist', [
'route' => 'artist_delete'
]);
}
return $menu;
}
...

Issue with collapsing menu using wp-bootstrap-navwalker

I'm developing my own wordpress theme for the first time, using bootstrap, and I've run into an issue when using the wp-bootstrap-navwalker.
I've created two menus, one that is visible in sm, md and lg, and one that is visible in xs. In xs it is supposed to be collapsed, and open on pressing the button, however after I added the wp-bootstrap-navwalker to my html, it is no longer working.
Here is my html:
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="description" content="Storhamar kunstløp har i dag nærmere 100 medlemmer og løpere på skøyteskole-, aspirant- og konkurransenivå. Her er man velkommen uansett ambisjonsnivå!">
<meta name="keywords" content="Storhamar, SIL, kunstløp, figure skating, Hamar, skøyter, idrettslag, kunstløpklubb, skøyteklubb">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php wp_title(''); ?></title>
<!--Fonts-->
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600,700' rel='stylesheet' type='text/css'>
<!--Icons-->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.2/css/font-awesome.min.css">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<header class="container-fluid hidden-xs">
<img src="<?php header_image(); ?>" class="img-responsive center-block">
</header>
<!-- Navbar ================================================== -->
<nav id="main-nav" class="navbar hidden-xs" data-spy="affix" data-offset-top="280">
<div class="container-fluid" id="main-nav-list">
<?php
wp_nav_menu( array(
'menu' => 'primary-lg',
'theme_location' => 'primary-lg',
'depth' => 1,
'container' => 'div',
'container_class' => 'container-fluid',
'container_id' => 'main-nav-list',
'menu_class' => 'nav navbar-nav main-nav',
'fallback_cb' => 'wp_bootstrap_navwalker::fallback',
'walker' => new wp_bootstrap_navwalker())
);
?>
</div>
</nav>
<!-- Mobile Navbar ================================================== -->
<nav id="mobile-nav" class="navbar mobile-nav navbar-default navbar-static-top visible-xs">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<?php
wp_nav_menu( array(
'menu' => 'primary-xs',
'theme_location' => 'primary-xs',
'depth' => 1,
'container' => 'div',
'container_class' => 'collapse navbar-collapse',
'container_id' => 'bs-example-navbar-collapse-1',
'menu_class' => 'nav navbar-nav',
'fallback_cb' => 'wp_bootstrap_navwalker::fallback',
'walker' => new wp_bootstrap_navwalker())
);
?>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<img src="<?php header_image(); ?>" class="img-responsive visible-xs center-block">
<main class="container">
Here is my functions.php:
<?php
if ( ! isset( $content_width ) ) {
$content_width = 660;
}
function SILkunstlop_setup() {
load_theme_textdomain('SILkunstlopLang', get_template_directory() . '/languages');
add_theme_support( 'title-tag' );
add_theme_support( 'automatic-feed-links' );
// Register Custom Navigation Walker
require_once('wp_bootstrap_navwalker.php');
register_nav_menus( array(
'primary-lg' => __( 'Hovedmeny stor', 'SILkunstlop-wp' ),
) );
register_nav_menus( array(
'primary-xs' => __( 'Hovedmeny liten', 'SILkunstlop-wp' ),
) );
register_nav_menus( array(
'sidebar-menu' => __( 'Sidemeny', 'SILkunstlop-wp' ),
) );
register_nav_menus( array(
'sidebar-menu2' => __( 'Sidemeny skøyteskole', 'SILkunstlop-wp' ),
) );
}
add_action('after_setup_theme', 'SILkunstlop_setup');
//Load the theme CSS
function theme_styles() {
wp_enqueue_style( 'bootstrap', get_template_directory_uri() . '/css/bootstrap.min.css');
wp_enqueue_style( 'main', get_template_directory_uri() . '/style.css');
}
//Load the theme JS
function theme_js() {
//Adds JQuery from Google's CDN. Code pulled from www.http://css-tricks.com/snippets/wordpress/include-jquery-in-wordpress-theme/
if (!is_admin()) add_action("wp_enqueue_scripts", "my_jquery_enqueue", 11);
function my_jquery_enqueue() {
wp_deregister_script('jquery');
wp_register_script('jquery', "http" . ($_SERVER['SERVER_PORT'] == 443 ? "s" : "") . "://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js", false, null);
wp_enqueue_script('jquery');
}
wp_enqueue_script( 'bootstrapjs', get_template_directory_uri() . '/js/bootstrap.min.js', array('jquery'), '', true );
wp_enqueue_script( 'theme_js', get_template_directory_uri() . '/js/custom.js', array('jquery'), '', true );
if ( is_singular() ) wp_enqueue_script('comment-reply');
}
add_action( 'wp_enqueue_scripts', 'theme_styles' );
add_action( 'wp_enqueue_scripts', 'theme_js' );
function new_excerpt_more( $more ) {
return '...';
}
add_filter('excerpt_more', 'new_excerpt_more');
/**
* Register our sidebars and widgetized areas.
*
*/
function arphabet_widgets_init() {
register_sidebar( array(
'name' => 'aktuelt',
'id' => 'aktuelt',
'before_widget' => '<div class="col-sm-8 hashtag">',
'after_widget' => '</div>',
'before_title' => '<h2>',
'after_title' => '</h2>',
) );
register_sidebar( array(
'name' => 'footer',
'id' => 'footer',
'before_widget' => '<div>',
'after_widget' => '</div>',
) );
}
add_action( 'widgets_init', 'arphabet_widgets_init' );
function searchResult() {
printf( __('Søkeresultat for: %s', 'SILkunstlopLang'), get_search_query());
}
$args = array(
// 'width' => 980,
'height' => 180,
'default-image' => get_template_directory_uri() . '/images/header.svg',
'uploads' => true,
);
add_theme_support( 'custom-header', $args );
$args = array(
'default-color' => 'A9C5DD',
'default-image' => get_template_directory_uri() . '/images/background.jpg',
'default-attachment' => 'fixed',
'default-repeat' => 'none',
'default-position-x' => 'center',
'default-position-y' => 'center',
'uploads' => true,
);
add_theme_support( 'custom-background', $args );
?>
Does anyone have a clue to where my issue is originating?
Thanks a lot for any clues given, and let me know if I should include some more information!
Best,
Elena
So I actually found the problem myself in the end, after studying the html once again with inspect element.
I didn't realise that the div around my nav is actually superfluous and just duplicated the container added by the menu. So after I removed the surrounding div with class of "collapse navbar-collapse" the menu collapsing menu worked again (opens on clicking the button).

howto create Walker to change <LI> to <a> and give class to <a>

what i want to achieved is this
<div class="someclass"> // in place of <ul>
<a class="item">Page Title</a>
<a class="item">Page Title</a>
<a class="item">Page Title</a>
.
.
.
</div>
This is the patter which is used by semantic UI for horizontal menu
I have achieved this much
<div class="ui secondary menu">
Services
Portfolio
Shop
</div>
by using code
<div class="ui secondary menu">
<?php
$menuParameters = array(
'menu' => 'top-menu',
'container' => false,
'echo' => false,
'items_wrap' => '%3$s',
'depth' => 0,
);
echo strip_tags(wp_nav_menu( $menuParameters ), '<a>' );
?>
</div>
But i want to add
class="item"
to
Services
Please guide..
thankx
Finally I able to do this..
<div id="menu1" class="ui secondary menu">
<?php
$menuParameters = array(
'menu' => 'top-menu',
'menu_class' => 'item',
'container' => false,
'echo' => false,
'items_wrap' => '%3$s',
'depth' => 0,
);
echo strip_tags(wp_nav_menu( $menuParameters ), '<a>' );
?>
</div>
<script>
jQuery( "#menu1 a" ).addClass( "item" );
</script>
You can use 'menu_class'=> 'item'
Example:
<div class="ui secondary menu">
<?php
$menuParameters = array(
'menu' => 'top-menu',
'menu_class' => 'item',
'container' => false,
'echo' => false,
'items_wrap' => '%3$s',
'depth' => 0,
);
echo strip_tags(wp_nav_menu( $menuParameters ), '<a>' );
?>
</div>
Read the codex about function wp_nav_menu, you're using it wrong, do something like this:
echo strip_tags(wp_nav_menu(
'items_wrap' => '<div id="%1$s" class="%2$s">%3$s</div>',
'menu_class' => 'myclass ui',
'echo' => false,
), '<a>');
In wordpress admin > appereance > menus, you can define classes for each link. Just make sure you've turned it on at the screen options.
But you can also do something like this to add a class.
Thankx Fermolina for your answer unfortunately it give me this output which dosent work
Code use
<div class="ui secondary menu">
<?php
$menuParameters = array(
'menu' => 'test-menu',
'menu_class' => 'item',
'container' => false,
'echo' => false,
'items_wrap' => '%3$s',
'depth' => 0,
);
echo strip_tags(wp_nav_menu( $menuParameters ), '<a>' );
?>
</div>
OUTPUT no class in
<div class="ui secondary menu">
Home
</div>

Create a Page Templete to Display Table Of Content for Custom Taxonomies

I have created a custom post type named "Training" & a Custom Taxonomy for the same named "Table Of Content"
I need to create a Page template to display Table Of Content Something like this
<div id="TableOfContents">
<ul class="sections">
<li> <a>Custom Taxonomy 1</a>
<ul class="sidenav">
<li class="selected"> Child Taxonomy 1
<ul class="items">
<li> Post Title 1 </li>
<li> Post Title 2 </li>
<li> Post Title 2 </li>
</ul>
</li>
<li class="selected"> Child Taxonomy 2
<ul class="items">
<li> Post Title 1 </li>
<li> Post Title 2 </li>
<li> Post Title 2 </li>
</ul>
</li>
</ul>
</li>
<li> <a>Custom Taxonomy 2</a>
<ul class="sidenav">
<li class="selected"> Child Taxonomy 1
<ul class="items">
<li> Post Title 1 </li>
<li> Post Title 2 </li>
<li> Post Title 2 </li>
</ul>
</li>
<li class="selected"> Child Taxonomy 2
<ul class="items">
<li> Post Title 1 </li>
<li> Post Title 2 </li>
<li> Post Title 2 </li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Here is the php code in functions.php for creating custom taxonomy
// Custom Taxonomy for Training
$labels = array(
'name' => 'Table of Content',
'singular_name' => 'Table of Content',
'search_items' => 'Search Table of Content',
'popular_items' => 'Popular Table of Content',
'all_items' => 'All Table of Content',
'parent_item' => 'Parent Table of Content',
'edit_item' => 'Edit Table of Content',
'update_item' => 'Update Table of Content',
'add_new_item' => 'Add New Table of Content',
'new_item_name' => 'New Table of Content',
'separate_items_with_commas' => 'Separate Table of Content with commas',
'add_or_remove_items' => 'Add or remove Table of Content',
'choose_from_most_used' => 'Choose from most used Table of Content'
);
$args = array(
'label' => 'Table of Content',
'labels' => $labels,
'public' => true,
'hierarchical' => true,
'show_ui' => true,
'show_in_nav_menus' => true,
'args' => array( 'orderby' => 'term_order' ),
'rewrite' => array( 'slug' => 'table-of-content', 'with_front' => false ),
'query_var' => true
);
register_taxonomy( 'tableofcontent', 'training', $args );
Thanks & Regards
Here is the final code I managed to working out:
<div class="content" role="main">
<?php $term = get_term_by('slug', get_query_var('term'), get_query_var('taxonomy'));
echo '<h3 class="tax-title">' . $term->name . '</h3>';
?>
<div id="TableOfContents">
<div class="ui-boxmenu">
<ul class="sections">
<?php
$taxonomyName = "tableofcontent";
$parent_terms = get_terms($taxonomyName, array(
'parent' => $term->term_id,
'orderby' => 'menu_order',
'hide_empty' => false
));
foreach ($parent_terms as $pterm) {
//Get the Child terms
$terms = get_terms($taxonomyName, array(
'parent' => $term->term_id,
'orderby' => 'menu_order',
'hide_empty' => false
));
foreach ($terms as $term) {
echo '<li><a>' . $term->name . '</a>';
$childs = get_terms($taxonomyName, array(
'parent' => $term->term_id,
'orderby' => 'menu_order',
'hide_empty' => false
));
echo '<ul class="sidenav">';
foreach ($childs as $child) {
echo '<li>' . $child->name . '';
$wpq = array ('taxonomy'=>'tableofcontent','orderby' => 'menu_order','order' => 'ASC','term'=>$child->slug);
$myquery = new WP_Query ($wpq);
$article_count = $myquery->post_count;
if ($article_count) {
echo "<ul class=\"items\">";
while ($myquery->have_posts()) : $myquery->the_post();
echo "<li>".$post->post_title."</li>";
endwhile;
echo "</ul>";
}
echo '</li>';
}
echo '</ul>';
echo '</li>';
}
}
?>
</ul>
</div>
</div>
<script language="javascript">
$('.ui-boxmenu').boxmenu();
</script>
<script type="text/javascript">
// Default add class selected to First Item in Box Menu
jQuery(document).ready(function($) {
$("ul.sections li:first").addClass("selected");
$("ul.sections li:first .sidenav li:first").addClass("selected");
$("ul.sections li:first .sidenav li ul.items").addClass("selected");
$("ul.sections li:first .sidenav li ul.items li:first").addClass("selected");
});
</script>
<?php
$singleterm = get_term_by('slug', get_query_var('term'), get_query_var('taxonomy'));
$args = array(
'post_type' => 'training',
'tableofcontent' => $singleterm->slug,
'orderby' => 'menu_order',
'showposts' => 1,
'order' => 'ASC',
);
$posts = get_posts( $args );
foreach ($posts as $post) : setup_postdata($post);
?>
<h2 class="content-subhead"><?php the_title() ?></h2>
<?php the_content() ?>
<?php endforeach; wp_reset_postdata(); ?>
</div>
Regards

Resources