Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating the submenus with Backbone.js

New in using Backbone.js and underscore.js, trying to create a list of submenus (second level) for my menulist (first level).

So this is my menulist I created in JSON (which I have confirmed exists by printing it to the browser console):

[
  {
    "name": "Sök kund",
    "path": 
    [
      {
        "subName": "Fondkonto",
        "subPath": "#fondkonto"
      },

      {
        "subName": "Kassakonto",
        "subPath": "#kassakonto"
      },

      {
        "subName": "Nytt sparande",
        "subPath": "#nyttsparande"
      }
    ]
  },

  {
    "name": "Ny kund",
    "path": "#new_customer"
  },
    {
    "name": "Dokument",
    "path": "#documents"
  },

  {
    "name": "Blanketter",
    "path": "#forms"
  }
]

And this is the code I put out to show in my index-file, which for now prints only the first-level:

<script type="text/template" id="menus">
  {{ _.each(menus, function(menu) { }}
    <li><a href="{{= menu.path }}">{{= menu.name }}</a>
      <ul>
        <li>
          <a href="{{= menu.path.subPath }}">{{= menu.path.subName }}</a>
        </li>
      </ul>
    </li>
  {{ }); }}
</script>

And in case you want to know how the view and model/collection are built:

var Menus = require("../collections/menus");

var AllMenus = Backbone.View.extend({

  el: "#menuContent",

  template: _.template(document.getElementById("menus").innerHTML),

  initialize: function() {

    "use strict";

    this.menus = new Menus();
    this.listenTo(this.menus, "reset", this.render);

    this.menus.fetch({
      reset: true,
      url: "./data/menus.json",
      success: function() {
        console.log("Succesfully loaded menus.json file.");
      },
      error: function() {
        console.log("There was some error trying to load and process menus.json file.");
      }
    });
  },

  render: function() {
    console.log( this.menus.toJSON());
    this.$el.html(this.template({ menus: this.menus.toJSON() }));
    return this;
  }

});

var viewMenus = new AllMenus();

Model:

var Menu = Backbone.Model.extend({
  defaults: {
    name: "",
    path: ""
  }
});

module.exports = Menu;

Collection:

var Menu = require("../models/menu");

var Menus = Backbone.Collection.extend({
  model: Menu
});

module.exports = Menus;

Don't mean to paste so much code, but necessary to make this so you understand how I built it up. But I got stuck by trying to show my subMenus with no success to it.

like image 586
Alexein Avatar asked Feb 01 '26 09:02

Alexein


1 Answers

Your data structure is wrong. You do not want to be switching between Strings and Arrays for your path value. A path should always be a String, and you should create a new property to hold the submenu Array; "submenu" would be a good name. Furthermore, your submenu items should not have subName and subPath as key names. These objects are conceptually the same as their parent objects and they should have the same keys, name and path.

Your revised data structure should look like the following:

var menus = [
    {
        "name": "Sök kund",
        "path": "#",
        "submenu": [
            {
                "name": "Fondkonto",
                "path": "#fondkonto"
            },
            {
                "name": "Kassakonto",
                "path": "#kassakonto"
            },
            {
                "name": "Nytt sparande",
                "path": "#nyttsparande"
            }
        ]
    },
    {
        "name": "Ny kund",
        "path": "#new_customer",
        "submenu": []
    },
    {
        "name": "Dokument",
        "path": "#documents",
        "submenu": []
    },
    {
        "name": "Blanketter",
        "path": "#forms",
        "submenu": []
    }
];

Next, we will update your template to iterate through the top level menu items and, conditionally, their submenus:

<script type="text/template" id="menus">
    {{ _.each(menus, function(menu) { }}
        <li>
            <a href="{{= menu.path }}">{{= menu.name }}</a>
            {{ if (menu.submenu && menu.submenu.length > 0) { }}
                <ul>
                    {{ _.each(menu.submenu, function (submenu) { }}
                        <li><a href="{{= submenu.path }}">{{= submenu.name }}</a></li>
                    {{ }); }}
                </ul>
            {{ } }}
        </li>
    {{ }); }}
</script>

Note: I assume you are doing something like the following to tell Underscore to override the default template settings with a Mustache-style syntax. I copied these settings from this answer.

_.templateSettings = {
    evaluate: /\{\{(.+?)\}\}/g,
    interpolate: /\{\{=(.+?)\}\}/g,
    escape: /\{\{-(.+?)\}\}/g 
};
like image 102
76484 Avatar answered Feb 04 '26 00:02

76484



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!