Javascript 带有angularjs的动态菜单栏

Javascript 带有angularjs的动态菜单栏,javascript,html,dom,angularjs,angularjs-directive,Javascript,Html,Dom,Angularjs,Angularjs Directive,我正在尝试使用Angularjs创建一个菜单栏。我以前也用Backbonejs做过类似的事情,但我很难弄清楚如何用angular做这件事 在我的html文件中,我有以下菜单占位符 <div id='menu1'></div> <div id='menu2'></div> <div id='menu3'></div> <div id='menu4'></div> <div id='menu5'&g

我正在尝试使用
Angularjs
创建一个菜单栏。我以前也用Backbonejs做过类似的事情,但我很难弄清楚如何用angular做这件事

在我的
html
文件中,我有以下菜单占位符

<div id='menu1'></div>
<div id='menu2'></div>
<div id='menu3'></div>
<div id='menu4'></div>
<div id='menu5'></div>
为简单起见,呈现的菜单项应如下所示:

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"
  })
  <ul>
    <li>organge</li>
    <li>apple</li>
    <li>banana</li>
  </ul>

同样,从主干/jquery背景来看,这是有道理的,但在angular中,这可能不是正确的做法。如果是这样,请让我知道如何使基本模板不了解模块的任何知识以及他们将菜单放在何处的假设(即,他们分配了菜单栏的哪个插槽)。我很高兴听到其他解决方案…

每个模块都应该定义其菜单加载程序:

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

factory('module1.menuLoader', function() {
    return function(callback) {
        callback(['oranges', 'bananas'])
    }
});
您的应用程序应该包含菜单指令,该指令只能在存在的情况下加载任何模块的菜单项

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;
                });
            }
        }
    };
}]); 
angular.module('app',['module1'])。
指令('menu',['$injector',函数($injector){
返回{
限制:“A”,
模板:
“
  • {{{item}}
”, 作用域:{}, 链接:函数($scope、$element、$attrs){ var menuLoaderName=$attrs.menu+'.menuLoader'; 如果($injector.has(menuLoaderName)){ var loaderFn=$injector.get(menuLoaderName); loaderFn(功能(菜单项){ $scope.items=menuItems; }); } } }; }]);
最终html:

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

运行应用程序后,仅加载module1菜单。其他菜单占位符仍为空

现场演示:


更新:如果要在模块端生成标记,最好的方法是将模板放入定义模板的模块中的$templateCache中,然后将templateName传递给应用程序

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;
                });
            }
        }
    };
}]);
angular.module('module1',[])。
工厂('module1.menuLoader',['$templateCache',函数($templateCache){
$templateCache.put('module1Menu','li ng repeat=“items中的item”>{{item}}');
返回函数(回调){
回调('Module1菜单',['oranges','bananas']))
}
}]);
角度模块('app',['module1']))
.directive('菜单',['$injector',函数($injector){
返回{
限制:“A”,
模板:
'',
作用域:{},
链接:函数($scope、$element、$attrs){
var menuLoaderName=$attrs.menu+'.menuLoader';
如果($injector.has(menuLoaderName)){
var loaderFn=$injector.get(menuLoaderName);
loaderFn(函数(menuTemplate、menuItems){
$scope.menuTemplate=menuTemplate;
$scope.items=menuItems;
});
}
}
};
}]);

每个模块都应定义其菜单加载程序:

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

factory('module1.menuLoader', function() {
    return function(callback) {
        callback(['oranges', 'bananas'])
    }
});
您的应用程序应该包含菜单指令,该指令只能在存在的情况下加载任何模块的菜单项

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;
                });
            }
        }
    };
}]); 
angular.module('app',['module1'])。
指令('menu',['$injector',函数($injector){
返回{
限制:“A”,
模板:
“
  • {{{item}}
”, 作用域:{}, 链接:函数($scope、$element、$attrs){ var menuLoaderName=$attrs.menu+'.menuLoader'; 如果($injector.has(menuLoaderName)){ var loaderFn=$injector.get(menuLoaderName); loaderFn(功能(菜单项){ $scope.items=menuItems; }); } } }; }]);
最终html:

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

运行应用程序后,仅加载module1菜单。其他菜单占位符仍为空

现场演示:


更新:如果要在模块端生成标记,最好的方法是将模板放入定义模板的模块中的$templateCache中,然后将templateName传递给应用程序

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;
                });
            }
        }
    };
}]);
angular.module('module1',[])。
工厂('module1.menuLoader',['$templateCache',函数($templateCache){
$templateCache.put('module1Menu','li ng repeat=“items中的item”>{{item}}');
返回函数(回调){
回调('Module1菜单',['oranges','bananas']))
}
}]);
角度模块('app',['module1']))
.directive('菜单',['$injector',函数($injector){
返回{
限制:“A”,
模板:
'',
作用域:{},
链接:函数($scope、$element、$attrs){
var menuLoaderName=$attrs.menu+'.menuLoader';
如果($injector.has(menuLoaderName)){
var loaderFn=$injector.get(menuLoaderName);
loaderFn(函数(menuTemplate、menuItems){
$scope.menuTemplate=menuTemplate;
$scope.items=menuItems;
});
}
}
};
}]);

在我的例子中,我希望保留定义菜单占位符的基本模板不受模块影响,即指向特定占位符的链接应该来自菜单的定义(在模块中)。菜单的标记(同样在每个模块中定义)可以是
,您可以在模块端生成标记。请看我的最新答案。谢谢,这正接近我的设想。剩下的唯一问题是基本模板端的
。如果他们只有普通的
id
s,并且可以在客户端指定目标(插入菜单的位置),那就更好了。如果需要id,那么将
$attrs.menu
更改为
$attrs.id
。如果您想改为
,请将
限制:“A”
更改为
限制“E”
。我们这里讨论的不是同一件事。在模块中,我想指定在基本模板中放置菜单的位置,例如通过指定
id
。在里面