AngularJS - CRUD 指令/服务/控制器模式



我想创建一些以某种方式与父控制器/作用域交互的指令。我以两种方式做 CRUD:A) 基于路线,如果您要编辑我使用$location将 url 更改为给定 url 的项目B) 基于同一页面,如果您单击它从 $scope.tpl 设置$scope.template 的项目上的编辑,那么在部分我有一个 ng-hide/show 隐藏并显示表格视图/详细信息视图。

我想要实现的可能是在我的指令中减少代码,也许使用更多基于服务的方法或提示?

指令

'use strict';
/* Directives */
var directives = angular.module("app.directives", ["ui"]);

function CrudCtrl($scope, $attrs, $location, $parse) {
    function getScope(scopeName) {
        scopeName = typeof scopeName || "$parent";
        var ngModel = $parse(scopeName, $scope);
        return ngModel($scope)
    }
    function refreshObjects(scopeName) {
        $scope.svc.query($scope.params, function(objects) {
            var parentScope = getScope(scopeName)
            parentScope.objects = objects
        });
    }
    if (!$scope.refreshObjects) {
        $scope.refreshObjects = function() {
            refreshObjects($attrs.modelname)
        }
    }
    if (!$scope.crudAdd) {
        $scope.crudAdd = function() {
            if ($attrs.url) {
                $location.path($attrs.url);
                return;
            } else {
                var parentScope = getScope($attrs.scope);
                parentScope.object = new $scope.svc();
                parentScope.template = parentScope.tpl;
            }
        }
    }
    if (!$scope.crudDelete) {
        $scope.crudDelete = function() {
            /* Fire off a delete and as a callback we update objects */
            $scope.svc.delete({accountId: $scope.account.uuid, id: $scope.object.id}, function() {
                refreshObjects($attrs.scopeName)
            });
        };
    }
    if (!$scope.crudEdit) {
        $scope.crudEdit = function() {
            if ($attrs.url) {
                $location.path($attrs.url);
                return;
            } else {
                var parentScope = getScope($attrs.scopeName);
                parentScope.object = $scope.object;
                parentScope.template = parentScope.tpl;
            }
        };
    }
    if (!$scope.crudSave) {
        $scope.crudSave = function() {
            var params = {}
            params.accountId = $scope.params.accountId
            if ($scope.object.id) { params.id = $scope.object.id }
            $scope.object.$save(params, function() {
                if ($attrs.url) {
                    $scope.back();
                } else {
                    refreshObjects($attrs.scopeName);
                    var parentScope = getScope($attrs.scopeName);
                    parentScope.template = undefined;
                }
            });
        };
    }
    if (!$scope.crudCancel) {
        $scope.crudCancel = function() {
            if (parentScope.template) {
                var parentScope = getScope($attrs.scopeName);
                parentScope.template = undefined;
            } else {
                $scope.back();
            }
        };
    };
};

directives.directive("refresh", function() {
    return {
        restrict: "E",
        replace: true,
        controller: CrudCtrl,
        scope: true,
        link: function(scope, element, attrs) {
            scope.display_text = attrs.text;
        },
        template: '<button class="btn btn-mini btn-primary" ng-click="refreshObjects()"><i class="icon-refresh"></i> Refresh</button>',
    };
});

/* Create something new */
directives.directive("create", function() {
    return {
        restrict: "E",
        replace: true,
        controller: CrudCtrl,
        scope: true,
        link: function(scope, element, attrs) {
            scope.display_text = attrs.text;
        },
        template: '<button class="btn btn-mini btn-success" ng-click="crudAdd()"><i class="icon-plus"></i> {{display_text || "Add"}}</button>',
    };
});

/* Delete button and update objects */
directives.directive("delete", function() {
    return {
        restrict: "E",
        replace: true,
        controller: CrudCtrl,
        scope: true,
        link: function(scope, element, attrs) {
            scope.display_text = attrs.text;
        },
        template: '<button class="btn btn-mini btn-danger" ng-click="crudDelete()"><i class="icon-remove icon-white"></i> {{display_text}}</button>',
    }
});
/* Helper to create a edit button */
directives.directive("edit", function() {
    return {
        restrict: "E",
        replace:  true,
        controller: CrudCtrl,
        scope: true,
        link: function(scope, element, attrs) {
            scope.display_text = attrs.text;
        },
        template: '<button class="btn btn-mini btn-info" ng-click="crudEdit()"><i class="icon-edit"></i> {{display_text || "Edit"}}</a>',
    }
});
/* Save the object and return to the previous page */
directives.directive("save", function() {
    return {
        restrict: "E",
        replace: true,
        controller: CrudCtrl,
        scope: true,
        link: function(scope, element, attrs) {
            scope.display_text = attrs.text;
        },
        template: '<button class="btn btn-success" ng-click="crudSave()"><i class="icon-ok"> {{display_text || "Save"}}</i></a>',
    };
});
/* Cancel the current action */
directives.directive("cancel", function() {
    return {
        restrict: "E",
        replace: true,
        controller: CrudCtrl,
        scope: true,
        link: function(scope, element, attrs) {
            scope.display_text = attrs.text;
        },
        template: '<button class="btn" ng-click="crudCancel()"><i class="icon-remove"></i> {{display_text || "Cancel"}}</button>'
    }
});

控制器示例

function BookingCtrl($scope, Booking) {
      $scope.svc = Booking;
      $scope.objects = $scope.svc.query($scope.params);
  }

然后在部分概述中,我有:

<div ng-hide="template">
<refresh></refresh>
<create url="/{{params.accountId}}/entity/add"></create>
<table class="table table-condensed table-hover">
    <thead>
        <tr>
            <th></th>
            <th>Name</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="object in objects">
            <td>
                <delete></delete>
                <edit url="/{{params.accountId}}/category/{{object.resource_id}}"></edit>
            </td>
            <td>{{object.resource_name}}</td>
            <td>{{object.description}}</td>
        </tr>
        </tr>
        </tr>
    </tbody>
</table>
</div>
<ng-show="template" ng-include src="template"></ng-show>

细节部分:

<div class="span4">
    <h3>Category: {{category.resource_name}}</h3>
    <form name="detail_form" class="form-horizontal">
        <div class="control-group">
            <label class="control-label"><strong>Name</strong></label>
            <div class="controls">
                <input required ng-model="object.resource_name" placeholder="Name" type="text" class="input-small">
            </div>
        </div>
        <div class="control-group">
            <label class="control-label"><strong>Description</strong></label>
            <div class="controls">
                <textarea ng-model="object.description" placeholder="Description" type="textarea" rows=5></textarea>
            </div>
        </div>
        <div class="control-group">
            <save scope-name="$parent.$parent"></save>
            <cancel scope-name="$parent.$parent"></cancel>
        </div>
    </form>
<pre>form = {{object | json}}</pre>
</div>

使用 $parent.$parent 似乎有些过分,如果有更好的方法来解决这个问题,请帮助我!

我会通过以下方式接近这种功能:

  • $resource投入使用。
  • 使用 ng-view 绑定 URL 和部分。 使用定位点链接到其他部分。
  • 根据每个部件的角色定义控制器。(通过服务$resource访问)

http://angularjs.org/#wire-up-a-backend 可能是一个例子。

最新更新