在我的网站上,我有一个导航栏组件,我想为每个最终加载的ng-view自定义。目前,我这样做如下。我有一个导航栏本身的NavCtrl,我的ng-view指令位于该控制器的范围之外。我使用导航栏服务来更改/覆盖导航栏中的功能,例如,我的每个视图都需要覆盖导航栏的保存按钮的单击处理程序。 NavbarService设置了保存功能。在NavCtrl中,$ scope.save = NavbarService.save
var app = angular.module('myApp', ['ngRoute', 'ngResource']);
app.config(function($routeProvider) {
$routeProvider.when('/world', {templateUrl : 'world.html', controller : 'WorldCtrl'}).otherwise({templateUrl : 'hello.html', controller : 'HelloCtrl'});
});
app.service('NavbarService', function() {
var message = 'Save button not clicked yet',
saveFunction = function() {
this.setMessage('Default save called');
};
this.save = function() {
_saveFunction();
};
this.setSaveFunction = function(funct) {
_saveFunction = funct;
};
this.setMessage = function(newMessage) {
message = newMessage;
};
this.getMessage = function() {
return message;
}
});
app.controller('NavCtrl', function($scope, $location, NavbarService) {
$scope.message = NavbarService.getMessage();
$scope.save = NavbarService.save;
$scope.world = function() {
$location.path('/world');
};
$scope.hello = function() {
$location.path('/hello');
};
$scope.$watch(NavbarService.getMessage, function(newValue) {
$scope.message = newValue;
});
});
app.controller('HelloCtrl', function($scope, NavbarService) {
$scope.init = function() {
NavbarService.setSaveFunction(function() {
NavbarService.setMessage('Save method called from the HelloCtrl');
});
};
});
app.controller('WorldCtrl', function($scope, NavbarService) {
$scope.init = function() {
NavbarService.setSaveFunction(function() {
NavbarService.setMessage('Save method called from the WorldCtrl');
});
};
});

<html lang="en">
<head>
<title>My App</title>
</head>
<body ng-app="myApp">
<nav ng-controller="NavCtrl">
<button ng-click="save()">Save</button>
<button ng-click="world()">Go to world</button>
<button ng-click="hello()">Go to hello</button>
<pre>{{message}}</pre>
</nav>
<div ng-view onload="init()"></div>
<script type="text/ng-template" id="hello.html">
<h2>Active view is Hello</h2>
</script>
<script type="text/ng-template" id="world.html">
<h2>Active view is World</h2>
</script>
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-route.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-resource.js"></script>
</body>
</html>
&#13;
我想知道我是否太复杂了。我认为只需将ng-view指令嵌套在NavCtrl的范围内即可实现同样的目的。这样我就可以在每个视图控制器中覆盖$ scope.save。
但大多数文档都声明服务是跨控制器共享资源的首选方式。有一种方式比另一种更好吗?为什么呢?
请指教。感谢。
答案 0 :(得分:0)
让我提出既不利用服务也不利用范围继承的东西。这是我试图解决的类似问题。我有通过 ui.router的 ui-view
加载的视图(我们基本上在这里谈论应用程序状态吗?)。我有我的正常应用程序nav&amp; subnav,像这样...
['findings', 'tasks', 'reports', 'blah']
......所有观点都很常见。但是我也有一些特定的UI视图,我希望连接到该视图的$ scope / controller。换句话说,我可能有一个特定于当前视图的下拉列表,以及另一个视图的预先输入。我选择用声明来解决这个问题,而不是试图强制一些继承覆盖范式。
首先,我制作了一个指令,它只是一个容器,用于容纳特定于视图的nav元素的声明元素。
.directive 'nxViewMenuContainer', [
()->
dir =
restrict: 'EAC'
link: ($scope, elem, attrs)->
if !elem.attr 'id'
elem.attr 'id', 'nx-view-menu-container'
$scope.$root.$on '$stateChangeSuccess', ->
elem.empty()
]
这是这样实现的:
<div class="navbar navbar-submenu2">
<ul class="nav navbar-nav navbar-submenu2">
<!-- container for dynamic view-specific menu content -->
<li nx-view-menu-container class="nav navbar-nav">
</li>
<!-- static nav items -->
<li class="nav navbar-nav" ng-repeat="nav in app.subnav">
<a><span class="current-del-name">{{nav.label}}</span></a>
</li>
此指令在每个视图上声明,并作为特定于视图的元素容器移动到上面的指令。
.directive 'nxViewMenu', [
()->
dir =
restrict: 'EAC'
link: ($scope, elem, attrs)->
elem.ready ->
name = attrs.nxViewMenu or '#nx-view-menu-container'
target = $(name)
if !target.length
return
target.empty()
target.append elem
]
在每个视图中,我可能希望动态菜单出现在其他位置(在本例中,在app-level的导航容器中),我在视图模板中声明它。
查看1
<div class="nx-view-menu">
<a class="btn btn-default">
<i class="fa fa-lg fa-bars nx-clickout-filter"></i>
<!--<label name="panel-title" style="color:#58585b; padding-left:5px;" class="nx-clickout-filter">Quick Links</label>-->
</a>
</div>
查看2
<div class="nx-view-menu">
<input typeahead="...">
</div>
查看3
<div class="nx-view-menu">
<date-picker>...</date-picker>
</div>
答案 1 :(得分:0)
但是,如果因为我的所有观看都需要该按钮,我将不得不在每个模板中重复
<button ng-click="save()">Save</button>
元素。
此评论清除了一些内容,在这种情况下,我不一定会推荐dynamic/declarative方法。相反,这个特定的用户体验可以被视为更多的静态用户体验,我做了一些不同的事情,仍然避免任何服务或范围继承。我建议使用以下内容:
您的应用级导航仍然可以借用其他答案的建议,但请忽略动态/声明性内容。导航看起来像:
<div class="navbar navbar-submenu2">
<ul class="nav navbar-nav navbar-submenu2">
<!-- container for dynamic view-specific menu content -->
<li nx-view-menu-container class="nav navbar-nav">
</li>
<!-- static nav items -->
<li class="nav navbar-nav">
<a ng-click="saveRqst()">
<span class="current-del-name">Save</span>
</a>
</li>
应用级控制器会有:
.controller 'appController', [
'$scope'
($scope)->
$scope.saveRqst = ->
$scope.$root.$broadcast 'saveRqst', <addt. data if applicable>
]
每个视图级别控制器这做了一些假设:
您的观点遵循普通的视图控制器范例(意味着它们不是具有隔离范围的特殊指令)
.controller&#39; someController&#39;,[ &#39; $范围&#39; ($范围) - &GT; $ scope。$ on&#39; saveRqst`,(data) - &gt; #do这个观点的东西 ]
现在我知道这看起来有点像范围继承位,但事实并非如此。无论如何,你必须为每个视图控制器逻辑定义你的保存逻辑,如果我已经理解你在问题中提出的内容以及其他答案的评论,那就无法解决。关于这个事件总线方法的一点好处就是它很容易跟踪逻辑。如果您记下您的代码,那么另一位有使用Java或Flex或其他任何经验的开发人员将能够轻松地快速实现其他视图。保存逻辑。
所以我提出了两种方法。一个是more dynamic, declarative approach,这个是更静态但又独一无二的方法。