最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Dynamic menu bar with angularjs - Stack Overflow

programmeradmin0浏览0评论

I'm trying to create a menu bar using Angularjs. I've done similar things before with Backbonejs, but I have a hard time getting my head around how to do this with angular.

In my html file, I have the following menu placeholder.

<div id='menu1'></div>
<div id='menu2'></div>
<div id='menu3'></div>
<div id='menu4'></div>
<div id='menu5'></div>

A number of my angular modules add a menu when they are loaded (in run). Each of them only reserves a particular slot (i.e. menu1..5), so they don't clash. When some modules aren't loaded, their menu would not show in the menu bar.

An angular module would conceptually look like:

angular.module('myModule3', [])
  .service('someService', function($http) {
    // get some data to populate menu (use $http)
    this.menuItems = ['orange', 'apple', 'banana']
  })

  .run(['someService', function(someService) {
    // create a rendered menu item
    ...
    // insert it at id="menu3"
  })

For sake of simplicity, the rendered menu item should look like:

  <ul>
    <li>organge</li>
    <li>apple</li>
    <li>banana</li>
  </ul>

I'm fairly new to angular, so I don't really know where to begin. I've been reading up on directives, but don't see how they fit in here, as they require some custom markup (maybe a custom menu tag containing the DOM target (i.e. menu..5). Also, how to connect this to a controller is not clear to me.

Update In addition to the above base template (containing arbitrary anchor points in the DOM) and the directive (which will produce a DOM element which will be inserted at these anchor points), a template will facilitate the creation of the DOM element. This template will be located in a separate file containing the position the directive's DOM element will be inserted to (as opposed to the usual case of directives in which an already existing tag will be replaced/inserted into specific markup that matches the directive's definition:

<menu ng-model="Model3DataService" target="#menu3">
  <ul>
    <li ng-repeat="for item in items"></li>
  </ul>
</menu>

Again, ing from a Backbone/jquery background this makes sense, but this may not be the right thing to do in angular. If so, please let me know how I could keep the base template free of any knowledge about the modules and assumptions of where they put their menu (i.e. which slot of the menu bar they allocate). I'm happy to hear about other solutions...

I'm trying to create a menu bar using Angularjs. I've done similar things before with Backbonejs, but I have a hard time getting my head around how to do this with angular.

In my html file, I have the following menu placeholder.

<div id='menu1'></div>
<div id='menu2'></div>
<div id='menu3'></div>
<div id='menu4'></div>
<div id='menu5'></div>

A number of my angular modules add a menu when they are loaded (in run). Each of them only reserves a particular slot (i.e. menu1..5), so they don't clash. When some modules aren't loaded, their menu would not show in the menu bar.

An angular module would conceptually look like:

angular.module('myModule3', [])
  .service('someService', function($http) {
    // get some data to populate menu (use $http)
    this.menuItems = ['orange', 'apple', 'banana']
  })

  .run(['someService', function(someService) {
    // create a rendered menu item
    ...
    // insert it at id="menu3"
  })

For sake of simplicity, the rendered menu item should look like:

  <ul>
    <li>organge</li>
    <li>apple</li>
    <li>banana</li>
  </ul>

I'm fairly new to angular, so I don't really know where to begin. I've been reading up on directives, but don't see how they fit in here, as they require some custom markup (maybe a custom menu tag containing the DOM target (i.e. menu..5). Also, how to connect this to a controller is not clear to me.

Update In addition to the above base template (containing arbitrary anchor points in the DOM) and the directive (which will produce a DOM element which will be inserted at these anchor points), a template will facilitate the creation of the DOM element. This template will be located in a separate file containing the position the directive's DOM element will be inserted to (as opposed to the usual case of directives in which an already existing tag will be replaced/inserted into specific markup that matches the directive's definition:

<menu ng-model="Model3DataService" target="#menu3">
  <ul>
    <li ng-repeat="for item in items"></li>
  </ul>
</menu>

Again, ing from a Backbone/jquery background this makes sense, but this may not be the right thing to do in angular. If so, please let me know how I could keep the base template free of any knowledge about the modules and assumptions of where they put their menu (i.e. which slot of the menu bar they allocate). I'm happy to hear about other solutions...

Share Improve this question edited Oct 12, 2013 at 6:40 orange asked Oct 11, 2013 at 23:49 orangeorange 8,09015 gold badges87 silver badges153 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

Each module should have its menu loader defined:

angular.module('module1', []).

factory('module1.menuLoader', function() {
    return function(callback) {
        callback(['oranges', 'bananas'])
    }
});

Your application should contain menu directive which can load menu items for any module only if exists.

angular.module('app', ['module1']).

directive('menu', ['$injector', function($injector) {
    return {
        restrict: 'A',
        template: 
            '<ul><li ng-repeat="item in items">{{item}}</li></ul>',
        scope: {},
        link: function($scope, $element, $attrs) {
            var menuLoaderName = $attrs.menu+'.menuLoader';
            if ($injector.has(menuLoaderName)) {
                var loaderFn = $injector.get(menuLoaderName);
                loaderFn(function(menuItems) {
                    $scope.items = menuItems;
                });
            }
        }
    };
}]); 

Final html:

<div class="content">
    <div menu="module1"></div>
    <div menu="module2"></div>
    <div menu="module3"></div>
</div>

After running the application only module1 menu will be loaded. Other menu placeholders remain empty.

Live demo: http://plnkr.co/edit/4tZQGSkJToGCirQ1cmb6


Updated: If you want to generate markup on the module side the best way is to put the template to the $templateCache in the module where it's defined and then pass the templateName to the application.

angular.module('module1', []).

factory('module1.menuLoader', ['$templateCache', function($templateCache) {
    $templateCache.put('module1Menu', '<ul><li ng-repeat="item in items">{{item}}</li></ul>');
    return function(callback) {
        callback('module1Menu', ['oranges', 'bananas'])
    }
}]);


angular.module('app', ['module1'])

.directive('menu', ['$injector', function($injector) {
    return {
        restrict: 'A',
        template: 
            '<div ng-include="menuTemplate"></div>',
        scope: {},
        link: function($scope, $element, $attrs) {
            var menuLoaderName = $attrs.menu+'.menuLoader';
            if ($injector.has(menuLoaderName)) {
                var loaderFn = $injector.get(menuLoaderName);
                loaderFn(function(menuTemplate, menuItems) {
                    $scope.menuTemplate = menuTemplate;
                    $scope.items = menuItems;
                });
            }
        }
    };
}]);
发布评论

评论列表(0)

  1. 暂无评论