First i'm sorry about my english, that's not my native langage.
I want create my navigation menu using tailwind and alpine js in Wordpress.
That's my menu :
<?php
wp_nav_menu(array(
'theme_location' => 'main-menu',
'container' => 'nav',
'container_class' => 'main-menu',
'menu_class' => 'flex gap-4 items-center',
'walker' => new Custom_Walker_Nav_Menu()
));
?>
Then my walker
class Custom_Walker_Nav_Menu extends Walker_Nav_Menu {
public function start_lvl(&$output, $depth = 0, $args = null) {
$indent = str_repeat("\t", $depth);
// Ajoutez la classe 'hidden' pour cacher les sous-menus par défaut
if ($depth === 0 && $args->walker->has_children) {
// Cet élément principal de niveau 0 a des enfants, ajoutons la classe spéciale
$output .= "$indent<ul x-show=\"open\" x-bind=\"dialog\" class=\"parent-menu-nav\">\n";
} else {
// Utilisez la classe par défaut pour les autres cas
$output .= "$indent<ul class=\"sub-menu\">\n";
}
}
public function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
$indent = ($depth) ? str_repeat("\t", $depth) : '';
$class_names = $value = '';
$attributes = '';
// Ajoutez ici les classes que vous souhaitez pour chaque élément de menu
$classes = empty($item->classes) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;
// Vérifiez si l'élément de menu a des sous-menus et ajoutez une classe spéciale
if (in_array('menu-item-has-children', $item->classes)) {
$classes[] = 'has-submenu';
// Ajoutez les attributs Alpine.js uniquement si l'élément a des enfants
// $attributes .= ' x-data="{ open: false }"';
$attributes .= ' x-bind="trigger"';
}
$output .= $indent . '<li id="menu-item-' . $item->ID . '" ' . $value . ' class="' . implode(' ', $classes) . '"' . $attributes . '>';
// Générez le lien de l'élément de menu
$attributes .= !empty($item->url) ? ' href="' . esc_url($item->url) . '"' : '';
$attributes .= !empty($item->target) ? ' target="' . esc_attr($item->target) . '"' : '';
$attributes .= !empty($item->xfn) ? ' rel="' . esc_attr($item->xfn) . '"' : '';
$attributes .= !empty($item->title) ? ' title="' . esc_attr($item->title) . '"' : '';
$item_output = $args->before;
// Ajoutez une div pour l'élément parent et les enfants
if (in_array('menu-item-has-children', $item->classes)) {
$item_output .= '<div class="submenuDiv relative"
x-data="{ open: false }" @mouseenter="open = true" @mouseleave="open = false"
x-data="drop()"
>';
}
$item_output .= '<a' . $attributes . '>';
$item_output .= $args->link_before . apply_filters('the_title', $item->title, $item->ID) . $args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
}
public function end_el(&$output, $item, $depth = 0, $args = null) {
$item_output = $args->before;
$item_output .= $args->after;
if (in_array('menu-item-has-children', $item->classes)) {
$item_output .= '</div>';
}
$output .= "</li>\n";
}
}
Sorry it's a bit long.
I have encountered two distinct issues in my project. First, I've successfully implemented the basic x-show feature from Alpine.js, which allows me to toggle the visibility of an element. However, when I added the "absolute top-10" class to this element, the dropdown closes immediately as soon as I move my cursor away from the trigger element. This behavior is not what I intend; instead, I want the dropdown to remain open when I hover over both the trigger and the dropdown menu. To address this, I'm attempting to utilize the x-bind directive.
The second issue relates to my attempt to integrate the x-bind directive into my code. However, I encountered two challenges:
First, I need to use an "id" to bind each individual element, but my initial attempt to do so was unsuccessful. Second, I encountered an error message stating that "trigger," "dialog," and "drop" are "not defined" in my code.
Here my index.js
import Alpine from 'alpinejs'
window.Alpine = Alpine
document.addEventListener('alpine:init', () => {
Alpine.data('dropdown', () => ({
open: false,
trigger: {
['x-ref']: 'trigger',
['@mouseenter']() {
this.open = true;
},
},
dialogue: {
['x-show']() {
return this.open;
},
['@mouseleave']() {
this.open = false;
},
},
}))
});
Alpine.start()
Can you please give me some advice about :
- the "not defined" (maybe i need to add the alpine script into the walker directly?)
- how to bind dynamically my differents triggers and dialogs element?
Thank you.