我正在开发一个简单的CRUD应用程序来查看数据库中的最终编辑通用对象/行。每种类型的CRUD相关操作(浏览,查看,创建,编辑,删除,搜索...)都具有相应类型的视图。该视图的实例类似于"浏览表A"或"编辑表B"的第45行。
视图具有可以创建子视图的操作,例如用户可能正在浏览表格并单击"编辑"在一个特定的行上。这使视图成为堆栈,只有最顶层的视图实际显示给用户。触发新操作时,视图会被压入堆栈,并在该操作完成或用户取消时弹出。
现在我的代码看起来像这样:
app.js:
angular.module('MyApp', [])
.controller('AppController', function($scope) {
var viewStack = [];
$scope.currentView = function() {
return viewStack[viewStack.length-1];
};
$scope.pushView = function(view) {
viewStack.push(view);
};
$scope.popView= function() {
viewStack.pop();
};
$scope.pushBrowseView = function(table) {
var view = {
type: "browse",
table: table,
rows: [],
refresh: function() {
// Load data into view.rows via AJAX
},
// ...
};
view.refresh();
$scope.pushView(view);
};
$scope.pushCreateView = function(table) {
var view = {
type: "create",
table: table,
newRow: {},
// ...
};
$scope.pushView(view);
};
$scope.pushEditView = function(table, row) {
var view = {
type: "edit",
table: table,
row: row,
// ...
};
$scope.pushView(view);
};
// More view types...
})
.controller('BrowseController', function($scope) {
$scope.create = function() {
$scope.pushCreateView($scope.currentView().table);
};
$scope.edit = function(row) {
$scope.pushEditView($scope.currentView().table, row);
};
})
.controller('CreateController', function($scope) {
$scope.submit = function() {
if(newRow.isValid()) {
// POST to server
window.alert('Row submitted');
$scope.popView();
} else {
window.alert('Not valid');
};
})
.controller('EditController', function($scope) {
// Similar to CreateController...
})
// More controllers for other view types
page.html中:
<body ng-app="MyApp" ng-controller="AppController">
<!-- Stuff -->
<button ng-click="popView()">Back</button>
<!-- More Stuff -->
<div id="theview" ng-switch="currentView().type">
<div ng-switch-when="browse" ng-controller="BrowseController">
<button ng-click="create()">New Row</button>
<table>
<!-- header goes here -->
<tr ng-repeat="row in currentView().rows">
<td><button ng-click="edit(row)">Edit</button></td>
<td ng-repeat="column in currentView().table.columns">
{{ row[column] }}
</td>
</tr>
</table>
</div>
<div ng-switch-when="create" ng-controller="CreateController">
<form>
<div ng-repeat="column in currentView().table.columns">
<label>{{ column }}</label>
<input
name="{{ column }}"
ng-model="currentView().newRow[column]">
</div>
</form>
<button ng-click="submit()">Submit</button>
</div>
<div ng-switch-when="edit" ng-controller="EditController">
<!-- Kinda like "create" -->
</div>
<!-- And the rest of the view types -->
</div>
</body>
很明显,但这显然是它的主旨。问题是应用程序有一个根作用域,每个类型视图都有一个子作用域。由于堆栈上每种类型的视图可能同时存在多个实例,因此每个视图的状态需要完全存储在viewStack
中的对象中,而不是存储在该视图类型中$scope
{{ 1}}。
这根本不是正确的做事方式。每个视图实例都有一个范围是有意义的,每个范围都是堆栈下面视图范围的子代。这样我就能从顶视图中自然地通过其他事件播放事件。我也不必用currentView()
为每个状态变量加前缀。但我能想到的唯一方法是使用递归指令,这可能会创建我不想要的深度嵌套的DOM元素。
这似乎是一种非常常见的设计模式。有没有更好的方法呢?
答案 0 :(得分:0)
按照您所描述的内容,我认为您的每个观点都更适合directive
with isolated scope
,而不是将每个观点放在公共范围内的viewStack
对象中。
在您的示例代码中,您将从AppController
获取表信息,并将它们存储在$ scope中以供您使用。我无法看到这些视图如何进入范围,但假设它们来自某个Web服务,您可以移动存储并将该数据提取到指令本身。例如,
app.directive('exampleView', ['myViewService`, function(myViewService) {
return {
restrict: 'E',
scope: {
'myTable': '=',
'myRows' : '=',
'onPopView': '&'
},
templateUrl: 'url/to/specific/view/template.html',
link: function($scope,element, attributes) {
//Logic for processing values and saving back to server/whatever as required
$scope.submit = function() {
if(newRow.isValid()) {
// POST to server
window.alert('Row submitted');
} else {
window.alert('Not valid');
}
};
if($scope.onPopView) {
// Tell parent controller that view is discarded?
$scope.onPopView();
}
}
};
}]);
onPopView
可能不适合您正在做的事情,但是将其用作创建父控制器挂钩的事件/回调的示例。这允许您在指令和父控制器之间分离职责。