具有嵌套模型的CRUD模型

时间:2013-03-14 16:31:09

标签: angularjs

我正在为我的应用管理员构建一个CRUD。我正在使用AngularJS和RESTfull API。 我可以成功保存一个简单的模型。但是当我有多对多的关系时,我在设置更新/创建表单时有点迷失。 我已经构建了一个Plunker来展示这个尝试: http://plnkr.co/edit/okeNuYBJ5f33gtu6WBoW

编辑:

现在使用复选框而不是下拉列表 Jason 建议:
http://plnkr.co/edit/okeNuYBJ5f33gtu6WBoW
但我的问题#3仍然没有修复。 如何保存这些更新/创建的关系?

所以我拥有与Role模型具有多对多关系的User模型。我能够显示/列出模型与它的关系。编辑用户时,我加载所有角色,以便UI可以构建要选择的角色下拉列表。我希望尽可能多的下拉,因为有关系。所以我在一个repeat =“userRole in user.role”中嵌套我的下拉列表。

进行更新时

第一个问题:如果用户有多个角色,则会显示尽可能多的下拉列表,但每个角色的所选角色是第一个关系。

第二个问题:我有一个按钮,可以为加载的用户添加新角色。我不确定我是否正确,因为在保存时我没有看到任何关于新附加角色的痕迹。

第三个问题:保存时我从角色中断开连接。仅更新用户。我的表格不对,但问题出在哪里?

进行创建时

我无法将角色链接到新用户。当我点击“添加新角色”时,角色列表的第一个角色会被推送给用户。但用户尚未创建。所以我收到了一个错误。我的表格再次错了。错误是什么? 保存新用户时,如何发布相关角色?

以下是一些代码,以防Plunker不起作用:

的index.html

<!DOCTYPE html>
<html lang="en" xmlns:ng="http://angularjs.org" data-ng-app="CRUD">
    <head>
         <meta charset="UTF-8" />
         <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap.no-icons.min.css" />
         <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/font-awesome/2.0/css/font-awesome.css" />
    </head>
    <body>
        <div class="span6" ng-view></div>
        <script src="http://code.angularjs.org/1.1.0/angular.min.js"></script>
        <script src="http://code.angularjs.org/1.1.0/angular-resource.js"></script>
        <script src="/crud.js"></script>
    </body>
</html>

crud.js 我的AngularJS特定代码

var users = [
    {'id':1,'name':'User 1', 'role':[{'id':1,'name':'Role 1'},{'id':2,'name':'Role 2'}]},
    {'id':2,'name':'User 2', 'role':[{'id':2,'name':'Role 2'}]},
    {'id':3,'name':'User 3', 'role':[{'id':1,'name':'Role 1'}]},
    {'id':4,'name':'User 4', 'role':[{'id':3,'name':'Role 3'},{'id':2,'name':'Role 2'}]}
];
var roles = [
    {'id':1,'name':'Role 1'},
    {'id':2,'name':'Role 2'},
    {'id':3,'name':'Role 3'}
];
/* Route */
angular.module('CRUD', []).
    config(['$routeProvider', function ($routeProvider) {
        $routeProvider.
            when('/create', {templateUrl: 'create.html',controller: ctrlCreate}).
            when('/read', {templateUrl: 'read.html',controller: ctrlRead}).
            when('/update/:userId', {templateUrl: 'update.html', controller: ctrlUpdate}).
            otherwise({redirectTo: 'read'});
    }]);


/* Controller CREATE */
function ctrlCreate($scope, $http, $location) {

    // dirty hack to find the user to update (in real life it would be loaded via REST)
    $scope.user = null;
    $scope.roles = roles;

    $scope.save = function() {
        // dirty hack to change the user (in real life it would be trigger a POST request to the server with updated model)
        users.push($scope.user);

        //if a scope digestion is already going on then it will get picked up and you won't have to call the $scope.$apply() method
        if(!$scope.$$phase) { //this is used to prevent an overlap of scope digestion
            $scope.$apply(); //this will kickstart angular to recognize the change
        }
        $location.path('/');
    };

    $scope.addRole = function(){
        $scope.user.role.push(roles[0]);
    };
}
ctrlCreate.$inject = ['$scope','$http','$location'];

/* Controller READ */
function ctrlRead($scope, $http, $location) {
    // dirty hack to find the user to update (in real life it would be loaded via REST)
    $scope.users = users;
    $scope.roles = roles;
}
ctrlRead.$inject = ['$scope','$http','$location'];

/* Controller UPDATE */
function ctrlUpdate($scope, $http, $location, $routeParams) {
    $scope.user = null;
    $scope.roles = roles;
    var id=$routeParams.userId;
    // dirty hack to find the user to update (in real life it would be loaded via REST)
    for (var i = 0; i < users.length; i++) {
        if (users[i].id==id) {
            $scope.user=users[i];
            console.debug($scope.user.role);
        }
    }

    $scope.save = function() {
        // dirty hack to change the user (in real life it would be trigger a PUT request to the server with updated model)
        for (var i = 0; i < users.length; i++) {
            if (users[i].id==id) {
                users[i] = $scope.user;
            }
        }
        //if a scope digestion is already going on then it will get picked up and you won't have to call the $scope.$apply() method
        if(!$scope.$$phase) { //this is used to prevent an overlap of scope digestion
            $scope.$apply(); //this will kickstart angular to recognize the change
        }
        $location.path('/');
    };

    $scope.addRole = function(){
        $scope.user.role.push(roles);
        console.debug($scope.user.role);
    };
}
ctrlUpdate.$inject = ['$scope','$http','$location', '$routeParams'];

现在我的模板:

create.html上

<form>
    <div class="control-group">
        <label class="control-label">Name</label>
         <input type="text" ng-model="user.name" placeholder="Enter a name here">
    </div>
    <div ng-repeat="userRole in user.role">
        <div class="control-group">
        <label class="control-label">Role</label>
        <select ng-selected="userRole.id">
            <option ng-repeat="role in roles" value="{{role.id}}">{{role.name}}</option>
        </select>
        </div>
    </div>
    <button ng-click="addRole()">Attach another role</button>
    <br />
    <br />
    <input type="submit" value="Submit" ng-click="save()" class="btn btn-primary">
    <a href="#/" class="btn">Cancel</a>
</form>

read.html

<br />
<table class="table table-bordered table-striped table-centred table-condensed table-hover">
    <thead>
        <tr>
            <th>User Name</th>
            <th>Role Name</th>
            <th>Action</th>
        </tr>
        </thead>
    <tbody>
        <tr ng-repeat="user in users">
            <td>{{user.name}}</td>
            <td>
                <span ng-repeat="role in user.role">{{role.name}}</span>
            </td>
            <td>
                <a title="edit" href="#/update/{{user.id}}"><i class="icon-edit"></i></a>
            </td>
        </tr>
    </tbody>
</table>
<br />
<a href="#/create" class="btn btn-primary"><i class="icon-plus"></i>&nbsp;Create a new user</a>

update.html

<form>
    <div class="control-group">
        <label class="control-label">Name</label>
         <input type="text" ng-model="user.name" placeholder="Enter a name here">
    </div>
    <div ng-repeat="userRole in user.role">
        <div class="control-group">
        <label class="control-label">Role</label>
        <select ng-selected="userRole.id">
            <option ng-repeat="role in roles" value="{{role.id}}">{{role.name}}</option>
        </select>
        </div>
    </div>
    <button ng-click="addRole()">Attach another role</button>
    <br />
    <br />
    <input type="submit" value="Submit" ng-click="save()" class="btn btn-primary">
    <a href="#/" class="btn">Cancel</a>
</form>

如果你看到一些错误的编码或错误的架构,请提出建议(我想我可以做一些指令,例如在添加一个新角色时可能吗?)。我希望这很清楚。 谢谢!

1 个答案:

答案 0 :(得分:1)

您可以通过重新设计UI来解决您遇到的前两个问题。而不是使用下拉列表使用复选框字段。示例plnkr: http://plnkr.co/edit/hgq2hmbRty7B9oryQnkm

一旦页面上的移动部件较少,希望调试第3个问题很容易。