Kelvin
Kelvin

Reputation: 199

Dynamic menu with jQuery json data

I have tried this but it doesn't work. I'm trying to make Dynamic Menu from jQuery json data. I have insert preview below.

I'm working on fully custom UI, so I plan not to use jQuery.UI.

var data = {
        menu: [{
            name: 'Women Cloth',
            link: '0',
            sub: null
        },{
            name: 'Men Cloth',
            link: '1',
            sub: [{
                name: 'Arsenal',
                link: '0-0',
                sub: null
            }, {
                name: 'Liverpool',
                link: '0-1',
                sub: null
            }, {
                name: 'Manchester United',
                link: '0-2',
                sub: null
            }]
        }]};

    var getMenuItem = function (itemData) {
        var item = $("<li>", {
            class: 'has-children',
            id: itemData.id
        }).append(
        $("<a>", {
            href: itemData.link,
            html: itemData.name,
            id: itemData.id + '-links',
        }));
        if (itemData.sub) {
            var subMenuItem = $("<li>", {
            class: 'has-icon'
            }).append(
            $("<a>", {
                href: itemData.link,
                class: 'submenu-title',
            }));
            var subList = $("<ul>", {
                class: 'secondary-dropdown',
            });
            $.each(itemData.sub, function () {
                subList.append(subMenuItem(this));
            });
            item.append(subList);
        }
        return item;
    };
    var $menu = $("#Menu");
    $.each(data.menu, function () {
        $menu.append(
            getMenuItem(this)
        );
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="Menu"></ul>

Below is the output I needed.

<li class="has-children" id="ID">
    <a id="ID-links" href="links">Women Clothing</a>
    <ul class="cd-secondary-dropdown is-hidden">
        <li class="go-back"><a>Back</a></li>
        <li class="has-icon"><a class="submenu">submenu 1</a></li>
        <li class="has-icon"><a class="submenu">submenu 2</a></li>
        <li class="has-icon"><a class="submenu">submenu 3</a></li>
        <li class="has-icon"><a class="submenu">submenu 4</a></li>
        <li class="has-icon"><a class="submenu">submenu 5</a></li>
    </ul>
</li>

<li class="has-children" id="ID">
    <a id="ID-links" href="links">Men Clothing</a>
    <ul class="cd-secondary-dropdown is-hidden">
        <li class="go-back"><a>Back</a></li>
        <li class="has-icon"><a class="submenu">submenu 1</a></li>
        <li class="has-icon"><a class="submenu">submenu 2</a></li>
        <li class="has-icon"><a class="submenu">submenu 3</a></li>
        <li class="has-icon"><a class="submenu">submenu 4</a></li>
        <li class="has-icon"><a class="submenu">submenu 5</a></li>
    </ul>
</li>

Upvotes: 2

Views: 1297

Answers (2)

Always Helping
Always Helping

Reputation: 14570

You were not using $.each function as you were supposed. you are passing this as args to your function. this will undefined in the function getMenuItem

In you $.each function you need to have args as index and data. Index return the number of each key in you JSON & data is the one you need to pass to your function.

Also in your cd-secondary-dropdown you need to add ul only once and not in $.each.

I have fixed up your code and is exactly working as you wanted in your output above.

Run snippet below to see it working.

var data = {
  menu: [{
    name: 'Women Cloth',
    link: '0',
    sub: null
  }, {
    name: 'Men Cloth',
    link: '1',
    sub: [{
      name: 'Arsenal',
      link: '0-0',
      sub: null
    }, {
      name: 'Liverpool',
      link: '0-1',
      sub: null
    }, {
      name: 'Manchester United',
      link: '0-2',
      sub: null
    }]
  }]
};

var getMenuItem = function(itemData) {

  var item = $("<li>", {
    class: 'has-children',
    id: itemData.id
  }).append(
    $("<a>", {
      href: itemData.link,
      html: itemData.name,
      id: itemData.id + '-links',
    }));


  if (itemData.sub) {
    //Add UL once only
    var subList = $("<ul>", {
      class: 'secondary-dropdown',
    }); 
    //Append go back
    var goBack = $("<li>", {}).append(
      $("<a>", {
        href: '',
        html: 'Go back',
        class: 'go-back',
      }));
    //Append go back
    subList.append(goBack);
    $.each(itemData.sub, function(index, data) {
      //Sub menu
      var subMenuItem = $("<li>", {
        class: 'has-icon'
      }).append(
        $("<a>", {
          href: data.link,
          html: data.name,
          class: 'submenu-title',
        }));

      subList.append(subMenuItem);
    });

    item.append(subList);
  }
  return item;
};


var $menu = $("#Menu");
$.each(data.menu, function(index, data) {
  $menu.append(getMenuItem(data));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="Menu"></ul>

Upvotes: 2

coder
coder

Reputation: 99

is this what you are trying to do? if yes, this is a way of doing it without jQuery

let data = {
        menu: [{
            name: 'Women Cloth',
            link: '0',
            sub: null
        },{
            name: 'Men Cloth',
            link: '1',
            sub: [{
                name: 'Arsenal',
                link: '0-0',
                sub: null
            }, {
                name: 'Liverpool',
                link: '0-1',
                sub: null
            }, {
                name: 'Manchester United',
                link: '0-2',
                sub: null
            }]
        }]};

const MENU_COMPONENT  = document.querySelector('#Menu');

for (const field in data.menu) {


const LI= document.createElement('li');
LI.setAttribute('class', 'has-children');
MENU_COMPONENT.appendChild(LI);
const LINK = document.createElement('a');
LINK.setAttribute('href', data.menu[field].link);
LINK.innerText = data.menu[field].name;
LI.appendChild(LINK);

const UL = document.createElement('ul');
UL.setAttribute('class', 'cd-secondary-dropdown is-hidden');
LI.appendChild(UL);

let SUBLEVEL_DATA = data.menu[field].sub;

  for (const sub in SUBLEVEL_DATA) {
    const SECOND_LEVEL_LI = document.createElement('li');
    SECOND_LEVEL_LI.setAttribute('class', 'has-icon');
    UL.appendChild(SECOND_LEVEL_LI);
    const SECOND_LEVEL_LINK = document.createElement('a');
    SECOND_LEVEL_LINK.setAttribute('href', SUBLEVEL_DATA[sub].link);
    SECOND_LEVEL_LINK.className = 'submenu';
         SECOND_LEVEL_LINK.innerText = SUBLEVEL_DATA[sub].name;
     SECOND_LEVEL_LI.appendChild(SECOND_LEVEL_LINK);
  }
  
}
<ul id="Menu"></ul>

Upvotes: 1

Related Questions