【发布时间】:2015-03-10 20:28:05
【问题描述】:
在 ASP.NET MVC 中编程时,我习惯于使用局部视图进行 CRUD 操作。现在我正在使用 Spring + AngularJS,我希望我能以类似的方式工作。到目前为止,通过使用 angular-ui-router,我已经成功地完成了一些基本的创建/更新分区。
例子:
layout.html
<!doctype html>
<html lang="en" ng-app="Example">
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<div class="container">
<nav class="row">
<ul class="nav nav-pills">
<li ui-sref-active="active"><a ui-sref="clients">Clients</a></li>
</ul>
</nav>
</div>
<div class="container">
<div class="row">
<div class="col-md-12" ui-view></div>
</div>
</div>
<script src="libs/jquery/dist/jquery.min.js"></script>
<script src="libs/angular/angular.min.js"></script>
<script src="libs/angular-ui-router/release/angular-ui-router.min.js"></script>
<script src="appjs/app.js"></script>
<script src="appjs/services.js"></script>
<script src="appjs/controllers/ClientController.js"></script>
<script src="appjs/filters.js"></script>
<script src="appjs/directives.js"></script>
</body>
</html>
/client/create.html
<h1>Create new client</h1>
<form name="clientForm">
<div ui-view></div>
</form>
/client/edit.html
<h1>Edit client</h1>
<form name="clientForm" ng-show="!loading">
<input type="hidden" name="id" ng-model="client.id" />
<div ui-view></div>
</form>
/client/_createOrEdit.html
<div class="form-group" ng-class="{'has-error': clientForm.name.$invalid}">
<label for="name">Name:</label>
<input id="name"
name="name"
type="text"
ng-model="client.name"
class="form-control"
required />
<span class="help-block" ng-show="clientForm.name.$error.required">Name field is required</span>
</div>
<div class="form-group" ng-class="{'has-error': clientForm.address.$invalid}">
<label for="address">Address:</label>
<input id="address"
name="address"
type="text"
ng-model="client.address"
class="form-control"
required />
<span class="help-block" ng-show="clientForm.address.$error.required">Address field is required</span>
</div>
<button class="btn btn-primary btn-lg btn-block"
ng-click="addOrUpdate(client)"
ng-disabled="clientForm.$invalid || clientForm.$pristine">Save</button>
app.js
App.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider
/* Client */
.state("clients", {
url : "/clients",
templateUrl : "clients/index",
controller : ClientListController
})
.state("clientCreate", {
abstract : true,
url : "/client",
templateUrl : "clients/create",
controller : ClientCreateController
})
.state("clientCreate.createOrEdit", {
url : "/create",
templateUrl : "clients/createOrEdit",
})
.state("clientEdit", {
abstract: true,
url : "/client/{id:[0-9]{1,9}}",
templateUrl : "clients/edit",
controller : ClientEditController
})
.state("clientEdit.createOrEdit", {
url : "/edit",
templateUrl : "clients/createOrEdit",
})
});
ClientController.js
var ClientListController = function($scope, $http) {
$scope.error = false;
$scope.loading = false;
$scope.getClientList = function() {
$scope.loading = true;
$http.get('clients/clientlist.json')
.success(function(clientList) {
$scope.clients = clientList;
$scope.loading = false;
})
.error(function() {
$scope.error = true;
$scope.loading = false;
});
}
$scope.getClientList();
};
var ClientCreateController = function($scope, $http, $location) {
$scope.client = {};
$scope.loading = false;
$scope.addOrUpdate = function(client) {
client.id = null;
$scope.loading = true;
$http.post('clients/createOrEdit', client)
.success(function() {
$scope.loading = false;
$location.path('/clients').replace(); //redirect to index
});
};
};
var ClientEditController = function($scope, $stateParams, $http, $location) {
$scope.client = {};
$scope.error = false;
$scope.loading = false;
$scope.getClientById = function(id) {
$scope.loading = true;
$http.get('clients/' + id + '/client.json')
.success(function(client) {
$scope.client = client;
$scope.loading = false;
})
.error(function() {
$scope.error = true;
$scope.loading = false;
});
}
$scope.addOrUpdate = function(client) {
$scope.loading = true;
$http.post('clients/createOrEdit', client)
.success(function() {
$scope.loading = false;
$location.path('/clients').replace(); //redirect to index
});
};
var selectedId = $stateParams.id;
$scope.getClientById(selectedId);
}
这是我目前的设置,我对它本身非常满意。然而,当试图通过增加一点复杂性来扩展它时,我陷入了困境。
假设我们的客户可以有多个位置,那么现在每个客户都有一个位置列表。
我想做的是制作用于创建/编辑位置的部分视图,并在编辑或创建客户端时为客户端拥有的每个现有位置显示它们、删除它们的能力以及添加新位置的能力,所有这些在客户端创建/编辑页面上。
在 ASP.NET MVC 中,我可以使用部分视图、BeginCollectionItem 和一些 jQuery 来完成此操作。我应该如何用角度来解决这个问题?
我尝试在内部使用带有 ng-include 的 ng-repeat,但是在尝试添加/删除位置时,ng-repeat 上没有任何反映,而且我也不喜欢这种方法。
我认为单击按钮时没有发生任何事情的原因与我在使用 insertLocation 方法单击按钮时在控制台中收到Async XHR deprecated warning 有关。
insertLocation() 看起来像这样
$scope.insertLocation = function() {
$scope.client.locations.push({});
}
并放置在创建和编辑控制器中,并且客户端变量也被编辑为如下所示
$scope.client = {locations: []};
请注意。我并不是在寻找解决这种情况的方法(尽管它会有所帮助),但更多的是对我的方法的建议。这是错的吗?如果是正确的心态,正确的方法是什么?
【问题讨论】:
-
我对布局有点困惑,为什么会有 CreateOREdit 视图?我明白了有一个用于创建客户端的创建视图,用于编辑的编辑,createoredit 做什么?
-
@Rohit 创建和编辑表单都有相同的输入,两者之间的唯一区别是编辑还有一个隐藏输入来存储已编辑项目的 id。因此 createOrEdit 包含创建和编辑操作通用的表单输入。其目的是尽可能地遵守 DRY 原则。
-
您的意思是对位置重复第二个
form-group1 次或更多次? (n 个位置 + 1 个空用于添加新位置或类似的东西?) -
@craigb 位置是具有 3 个属性的对象。我想要一个包含这些属性中的每一个的表单输入的部分视图,并且 1. 为客户拥有的每个现有位置重复 n 次,并用相应的数据(以及隐藏的 id 输入)填充它,2. 在按下 + 按钮添加相同的部分,没有隐藏的 id 输入和空输入。
标签: angularjs angularjs-ng-repeat angular-ui