0

I want to make a multi-level menu, from database. In the database I have these collumns: 'id', 'name', 'parent_id', 'url'. If item has no children, 'parent_id' is set to 0.

I have used this tutorial: Laravel 4 - Eloquent. Infinite children into usable array? , and it works great, this is the result:

  • Home
    • Register
      • Hello
    • Login
      • Yeah
      • Where
        • Is
          • My
            • Mind

The question is: how do I set the required classes, for Zurb Foundation to work? In this case, I would like to only see [Home], then after I click on it [Register] and [Login] should appear, and so on.

The very last function, that prints out HTML is as such:

    private function htmlFromArray($array) {
    $html = '';
    foreach($array as $k=>$v) {
        $html .= "<ul>";
        $html .= '<li><a href="#">'.$k."</a></li>";
        if(count($v) > 0) {
            $html .= $this->htmlFromArray($v);
        }
        $html .= "</ul>";
    }
    return $html;
    }

And this is the example of dropdown menu from the Zurb website:

    <a href="#" data-dropdown="drop1">Has Dropdown</a>
    <ul id="drop1" class="f-dropdown" data-dropdown-content>
       <li><a href="#">This is a link</a></li>
       <li><a href="#">This is another</a></li>
       <li><a href="#">Yet another</a></li>
    </ul>

So my HTML should look like this:

    <a href="#" data-dropdown="drop1">Home</a>
    <ul id="drop1" class="f-dropdown" data-dropdown-content>
       <li><a href="#" data-dropdown="drop2">Register</a></li>
          <ul id="drop1" class="f-dropdown" data-dropdown-content>
             <li><a href="#">Hello</a></li>
          </ul>
       <li><a href="#" data-dropdown="drop3">Login</a></li>
          <ul id="drop1" class="f-dropdown" data-dropdown-content>
             <li><a href="#">Yeah</a></li>
             <li><a href="#" data-dropdown="drop4">Where</a></li>
                <ul id="drop1" class="f-dropdown" data-dropdown-content>
                   <li><a href="#">Is</a></li>
                </ul>
          </ul>
    </ul>

And I have no idea, how to achieve this, so any help would be appreciated. Or if anyone has another way of creating dynamic, multilevel menus, please share!

Community
  • 1
  • 1
Lynce
  • 5
  • 1
  • 4

1 Answers1

0

From what I can see your original array looks something like this:

 $array = array(
    'Home' => array(
            'Register' => array(
                'Hello' => array()
            ),
            'Login' => array(
                'Yeah' => array(),
                'Where' => array(
                    'Is' => array(
                        'My' => array()
                    )
                ),
            )

    )
);

I chose to handle the top level links in a separate function as those wont have ul/li wrappers.

function dropdownList($array) {
    $html = "";
    $dropDownId = 0;

    foreach ($array as $k => $v) {

        if(count($v) > 0) {
            $hasChildren = true;
            $dropDownId++;
        } else {
            $hasChildren = false;
        }

        $html = '<a href="#"' . ($hasChildren ? ' data-dropdown="drop' . $dropDownId . '"' : '') . '>' . $k . '</a>';

        if($hasChildren) {
            $html .= children($v, $dropDownId);
        }

    }

    return $html;
}

function children($array, &$dropDownId) {

    $html = '<ul id="drop' . $dropDownId . '" class="f-dropdown" data-dropdown-content>';

    foreach($array as $k=>$v) {

        if(count($v) > 0) {
            $hasChildren = true;
            $dropDownId++;
        } else {
            $hasChildren = false;
        }

        $html .= '<li><a href="#"' . ($hasChildren ? ' data-dropdown="drop' . $dropDownId . '"' : '') . '>'.$k."</a>\n";
        if($hasChildren) {
            $html .= children($v, $dropDownId);
        }
        $html .= '</li>';
    }
    $html .= "</ul>";
    return $html;
}

Output:

echo dropdownList($array);

<a href="#" data-dropdown="drop1">Home</a>
<ul id="drop1" class="f-dropdown" data-dropdown-content>
    <li>
        <a href="#" data-dropdown="drop2">Register</a>
        <ul id="drop2" class="f-dropdown" data-dropdown-content>
            <li>
                <a href="#">Hello</a>
            </li>
        </ul>
    </li>
    <li>
        <a href="#" data-dropdown="drop3">Login</a>
        <ul id="drop3" class="f-dropdown" data-dropdown-content>
            <li>
                <a href="#">Yeah</a>
            </li>
            <li>
                <a href="#" data-dropdown="drop4">Where</a>
                <ul id="drop4" class="f-dropdown" data-dropdown-content>
                    <li>
                        <a href="#" data-dropdown="drop5">Is</a>
                        <ul id="drop5" class="f-dropdown" data-dropdown-content>
                            <li>
                                <a href="#">My</a>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

Im guessing somewhere into the nesting you want to have an acutal link instead of #. This doesnt handle that, but you could e.g. check if $v is a string before you check it for children and in that case swap out the # in href.

That beeing said, have you considered using the top bar menu in foundation. It seems more suited :) http://foundation.zurb.com/docs/components/topbar.html

I have a set this up in Laravel, so let me know if you are interested in that solution.

Fiffen
  • 36
  • 3