Jump to content

Menu Builder


kongondo

Recommended Posts

This bug has been already reported by one of my colleagues in 2021, but nothing has been corrected so far. If your profile is set in a language other than the default language, and you are building a menu with the MenuBuilder module, your menu won't appear correctly in the other language.

1639174403_CleanShot2022-11-08at15_34_29.png.ce07791ca729c0794681ba173637af93.png

If you switch back to the original language, you can edit it.

668728021_CleanShot2022-11-08at15_44_43.png.49293712e8586db9538c55635bf534dd.png

Also, the menu is pretty useless because it doesn't show correctly in pages.

935616135_CleanShot2022-11-08at15_53_52.png.c2bf052ec0adc3e151be1023c683c8b9.png

Which is a real problem in one of our actual project

1173005745_CleanShot2022-11-08at15_57_50.png.8769b0b687c4f45245d759d0b0b954c9.png

Is there a solution for that?

 

Edited by Spiria
Typo
Link to comment
Share on other sites

Hey @Spiria — just a heads-up that I have merged your post to the Menu Builder support thread. Official support thread is the best way to reach module author. Looking back to the report in 2021, it looks like that earlier report might've just gone unnoticed.

  • Like 1
Link to comment
Share on other sites

19 hours ago, Spiria said:

This bug has been already reported by one of my colleagues in 2021, but nothing has been corrected so far. If your profile is set in a language other than the default language, and you are building a menu with the MenuBuilder module, your menu won't appear correctly in the other language.

What @teppo said. Apologies this slipped under the radar. I'll have a look this weekend.

Link to comment
Share on other sites

On 11/17/2022 at 7:34 PM, Spiria said:

@kongondo Where you able to figure out what the problem is?

Hi @Spiria,

Sorry, didn't get a chance to look at it. There are two 'issues' you have reported:

#1 If your profile is set in a language other than the default language, and you are building a menu with the MenuBuilder module, your menu won't appear correctly in the other language.

I am working on a fix now. I hope to fix over the weekend. No promises though.

#2 if you build the menu with language in your profile other than the default language, the menu will not translate correctly to the language chosen by a visitor, as my examples show.

By default Menu Builder will display the title of the page as it was when it was added to the menu. If you want it to be dynamic depending on the current title and current language, you need to use the default_title option as documented here. For example:

<?php

namespace ProcessWire;

$menu = $modules->get('MarkupMenuBuilder');
// render the menu by title and show the current title of the page in the user's language
$content =  $menu->render('My Menu', ['default_title' => 1]);

 

 

 

Link to comment
Share on other sites

On 11/17/2022 at 7:34 PM, Spiria said:

@kongondo Where you able to figure out what the problem is?

Hi @Spiria

Could you please test version 0.2.8 currently on the dev branch? You will have to install it manually. It fixes the issue:

Quote

If your profile is set in a language other than the default language, and you are building a menu with the MenuBuilder module, your menu won't appear correctly in the other language.

Please let me know if it works. 

Thanks.

Link to comment
Share on other sites

Sorry for the delay. My colleague said the problem is solved in part:

When I add a page to a menu in another language than default, the url is now OK, but the title is displayed in the wrong language as before

A page with the site's page selector, not a custom addition.

 

Link to comment
Share on other sites

  • 2 weeks later...
On 11/23/2022 at 7:57 PM, Spiria said:

but the title is displayed in the wrong language as before

I don't understand this. 

  1. What title are you referring to? The titles of menus that are displayed in the dashboard that shows all Menu Builder menus in the backend?
  2. What is the wrong language in this case?
  3. A screenshot with English explanations would help.
Link to comment
Share on other sites

Hi kogondo, I am a colleague of Spiria. In this exemple, the default language is French. if the profile of the user who modify the menu is english, the url of the item that will be displayed is correct, but not the title. 

 

Screenshot 2022-12-04 at 2.34.55 PM.png

Link to comment
Share on other sites

11 minutes ago, GEN- said:

Hi kogondo, I am a colleague of Spiria. In this exemple, the default language is French. if the profile of the user who modify the menu is english, the url of the item that will be displayed is correct, but not the title. 

 

Screenshot 2022-12-04 at 2.34.55 PM.png

Hi @GEN-,

Thanks for clarifying. Did you see my response above about this with respect to the option default_title?

 

 

Link to comment
Share on other sites

Thanks Kogondo, I didn't see this comment. I just saw the one from November 20th talking about the version 0.2.8 on the dev branch. I just tried getMenuItems(1705, 1,['default_title' => 1]) and it works.

Thanks again

  • Like 1
Link to comment
Share on other sites

3 minutes ago, GEN- said:

Thanks Kogondo, I didn't see this comment. I just saw the one from November 20th talking about the version 0.2.8 on the dev branch. I just tried getMenuItems(1705, 1,['default_title' => 1]) and it works.

Thanks again

Glad you got it sorted! 😄.

By the way, I know there are some CSS issues that need fixing. Something changed in ProcessWire that is messing up the page selections. I have accepted a PR for this in the Project  in GitHUb and will be merging with dev 0.28 this week now that you have confirmed 0.28 works. Thanks.

Link to comment
Share on other sites

  • 2 weeks later...

Hello,

I'm strugling to create the menu, and somehow can't make it to look the same as original.
It somehow works, but no quite right. Not sure what is wrong here. Any help appreciated.

I need:

<ul class="navbar-nav ms-auto">
	<li class="nav-item dropdown"> <span class="nav-link active" data-bs-toggle="dropdown" aria-expanded="false"> Home <i class="ti-angle-down"></i></span>
		<ul class="dropdown-menu last">
			<li class="dropdown-item"><a href="index.html">Home Layout 01</a></li>
			<li class="dropdown-item"><a href="index2.html">Home Layout 02</a></li>
			<li class="dropdown-item"><a href="index3.html">Home Layout 03</a></li>
			<li class="dropdown-item active"><a href="index4.html">Home Layout 04</a></li>
			<li class="dropdown-item"><a href="index5.html">Home Layout 05</a></li>
			<li class="dropdown-item"><a href="index6.html">Home Layout 06</a></li>
			<li class="dropdown-item"><a href="index7.html">Home Layout 07</a></li>
		</ul>
	</li>
</ul>

My code:

<?php

function buildMenuFromObject($parent = 0, $menu, $first = 0) {
  if(!is_object($menu)) return;
  $out = '';
  $has_child = false;
  foreach ($menu as $m) {
	$newtab = $m->newtab ? " target='_blank'" : '';            
	// if this menu item is a parent; create the sub-items/child-menu-items
	if ($m->parentID == $parent) {// if this menu item is a parent; create the inner-items/child-menu-items
		// if this is the first child
		if ($has_child === false) {                    
			$has_child = true;// This is a parent                        
			if ($first == 0){                            
			  $out .= "<ul class='navbar-nav ms-auto'>\n";                            
			  $first = 1;
			}                        
			else $out .= "\n<ul class='dropdown-menu last'>\n";
		}
		$class = $m->isCurrent ? 'active' : '';
		// a menu item
		$out .= '<li class="nav-item dropdown"><span class="nav-link  ' . $class . '"  data-bs-toggle="dropdown" aria-expanded="false"><a href="' . $m->url . '">'. $m->title .'</a>';                    
		// if menu item has children
		if ($m->isParent) {
		  $out .= '<i class="ti-angle-down"></i></span>';
		}
		
		else $out .= '<li class="nav-item dropdown">' .
		'</a>';         
		// call function again to generate nested list for sub-menu items belonging to this menu item. 
		$out .= buildMenuFromObject($m->id, $menu, $first);
		$out .= "</li>\n";
	}// end if parent
  
  }// end foreach
  if ($has_child === true) $out .= "</ul>\n";    
  return $out;
}


##################################

$mb = $modules->get('MarkupMenuBuilder');// get Menu Builder

$menu = 1031;// pass an ID

$options = array('default_title'=> 1, 'default_class'=> 'dropdown-item', 'current_class_level' => 6);
/* grab menu items as a WireArray with Menu objects */
$menuItems = $mb->getMenuItems($menu, 2, $options);// called with options and 2nd argument = 2 {return Menu (WireArray object)}
?>
		   
<?php
  // build menu from array (example 1b only)
  echo buildMenuFromObject(0, $menuItems);
?>

Thank you very much

R

Link to comment
Share on other sites

  • 1 month later...

Hello everyone,

I have following markup for my menu build with module "MenuBuilder" and I want to update it to PHP 8. I am not very expirienced with PHP so I cant find a solution. Here is the code:

<?php namespace ProcessWire;
/*
 *
 * Main Menu.
 *
 */
?>
    <?php
/**
 * Builds a nested list (menu items) of a single menu.
 *
 * A recursive function to display nested list of menu items.
 *
 * @access private
 * @param Int $parent ID of menu item.
 * @param Array $menu Object of menu items to display.
 * @param Int $first Helper variable to designate first menu item.
 * @return string $out.
 *
 */
function buildMenuFromObject($parent = 0, $menu, $first = 0) {
    if(!is_object($menu)) return;

    $out = '';
    $has_child = false;

    foreach ($menu as $m) {
        $newtab = $m->newtab ? " target='_blank'" : '';
        // if this menu item is a parent; create the sub-items/child-menu-items
        if ($m->parentID == $parent) {// if this menu item is a parent; create the inner-items/child-menu-items
            // if this is the first child
            if ($has_child === false) {
                $has_child = true;// This is a parent
                if ($first == 0){
                    $out .= "\n<ul class='uk-navbar-nav'>";
                    $first = 1;
                }
                else {
                    $out .=
                        "\n\t<div class='uk-navbar-dropdown'>" .
                        "\n\t\t<ul class='uk-nav uk-navbar-dropdown-nav'>";
                }
            }
            // active/current menu item
            $class = $m->isCurrent ? ' class="uk-active"' : '';

            // a menu item
            $out .= "\n\t<li$class><a href='{$m->url}{$newtab}'>{$m->title}</a>";

            // call function again to generate nested list for sub-menu items belonging to this menu item.
            $out .= buildMenuFromObject($m->id, $menu, $first);
            if ($m->isParent) $out .= "\n\t</div>\n";// close div.uk-navbar-dropdown
            $out .= "</li>";

        }// end if parent

    }// end foreach

    if ($has_child === true) $out .= "\n</ul>";

    return $out;

}

// example usage

$mb = $modules->get('MarkupMenuBuilder');
$menuItemsAsObject = $mb->getMenuItems(1073, 2);
$menu = buildMenuFromObject(0, $menuItemsAsObject);

echo $menu;
?>

As far as I found out, the problem is the function with the $menu variable. But I can't find a way to update this.

May someone can help me out!

thanks in advance

Link to comment
Share on other sites

  • 4 weeks later...
  • 1 month later...

In a multilingual environment I get the following error, wehen sorting menu-items

TypeError

method_exists(): Argument #1 ($object_or_class) must be of type object|string, null given
File: .../modules/MarkupMenuBuilder/ProcessMenuBuilder.module:2602

2602: if($language != null && method_exists($pages->get($itemID)->title, 'getLanguageValue')) $itemTitle = $pages->get($itemID)->title->getLanguageValue($language);// title of each PW page in this array

This works for me:

 

// multilingual environments
if($language != null && $itemID && method_exists($pages->get($itemID)->title, 'getLanguageValue')) $itemTitle = $pages->get($itemID)->title->getLanguageValue($language);// title of each PW page in this array


 

  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...

Hello

I'm having some problems with my menu. I want to show only first level of my menu without any children but can't make it work, no matter what I do. It always shows children. Any idea?
It is a multilanguage site!

I'm tried:

<?php
$menu = $modules->get('MarkupMenuBuilder');
$options = array(
    'max_levels' => 1,
    'include_children' => 0
);
echo $menu->render(1030, $options);
?>	

But it's not working. Am I missing something or is there some bug maybe. Tried all sorts of codes but childrens are always there.

Thank you

R

Link to comment
Share on other sites

Hi @Roych,

4 hours ago, Roych said:

I want to show only first level of my menu without any children

There is no setting for this currently. 'include_children' applies to only to the 'real/natural ProcessWire children pages. For instance, if my ProcessWire page tree is as follows:

Home
	About
    	History
        Mission
        Team
	Services
    Plans

And your Menu Builder Menu is as follows (in the backend):

Home
About
	Services

If you use 'include_children', your rendered menu will display as follows:

Home
About
	Services
    History
    Mission
    Team

As you can see, 'include_children' will grab the 'real' children (ProcessWire pages) of 'About'  and display them in the menu. However, without 'include_children', your menu will be rendered as follows:

Home
About
	Services

You cannot programmatically disables 'Services' from not showing. I.e,, there is no option for you to get:

Home
About

However, you can achieve what you want by using getMenuItems()

You can have getMenuItems() return an object (WireArray). You can then use WireArray methods to remove children items from the WireArray. Finally, given that this is a single level menu, you can just loop through the filtered WireArray and display them in your markup. Example code (untested):

<?php

namespace ProcessWire;

$menu = $modules -> get('MarkupMenuBuilder');
// get the menu items for menu with ID 1030
/** @var WireArray $menuItems */
$menuItems = $menu->getMenuItems(1030);
// OR, if passing options
// $menuItems = $menu->getMenuItems(1030, 2, $options);
// ------
// grab top level menu items only
// they do not have a parent, i.e. parent_id == 0
/** @var WireArray $topLevelMenuItems */
$topLevelMenuItems = $menuItems->find("parentID=0");// you could also use (destructive) filter

$out = "<ul>";
foreach($topLevelMenuItems as $topLevelMenuItem){
  $out .= "<li><a href='{$topLevelMenuItem->url}'>{$topLevelMenuItem->title}</a></li>";
}
$out .= "</ul>";

Hope this helps.

Link to comment
Share on other sites

not realy working. The children are not native children of a page, they are made with MenuBuilder drag&drop option. I want those in my header main menu, but in my footer I only want to show the first row.

 

Link to comment
Share on other sites

Ohhh, with a lot of thinking, this is somehow working But not as expected 😉
 

<?php
$homepage = $pages->get(1); // get the homepage
$topLevelPages = $homepage->children("parent_id=1"); // get the top-level pages

$out = "";
foreach ($topLevelPages as $page) {
  $out .= "<li><a href='{$page->url}'>{$page->title}</a></li>";
}
if ($out != "") {
  $out = "<ul>" . $out . "</ul>";
  echo $out;
} else {
  echo "No menu items found.";
}

?>

 

Edited by Roych
Forget this, it's not working!
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...