angularjs:使用$ resource将async服务注入指令

时间:2016-02-17 08:10:33

标签: angularjs angularjs-directive angularjs-scope angularjs-service

我正在努力让我的头脑仍然围绕angularJS和指令。

我有一个现有的REST服务,它按如下方式输出JSON数据(格式化为可读性):

{"ApplicationType":
    ["Max","Maya","AfterEffects","Nuke","WebClient","Other"],
"FeatureCategory":
    ["General","Animation","Compositing","Management","Other"],
"FeatureStatus":
    ["Completed","WIP","NotStarted","Cancelled","Rejected","PendingReview"],
"BugStatus":
    ["Solved","FixInProgress","NotStarted","Dismissed","PendingReview"]}

然后我有一个服务(似乎工作正常)来检索我希望注入我的指令的数据。

(function () {
'use strict';

var enumService = angular.module('enumService', ['ngResource']);

enumService.factory('Enums', ['$resource',
function ($resource) {
    return $resource('/api/Enums', {}, {
        query: { method: 'GET', cache: false, params: {}, isArray: false }
    });
}
]); })();

我的意图是使用来自json响应的数据绑定到html选择器'options',以保持REST服务和角度之间的代码之间的数据一致(即json数据描述强类型模型来自c#的数据,例如Enum.GetNames(typeof(ApplicationType)))

projMgrApp.directive('enumOptions', ['Enums',
function (Enums) {
    return {
        restrict: 'EA',
        template: '<option ng-repeat="op in options">{{op}}</option>',
        scope: {
            key: '@'
        },
        controller: function($scope) { },
        link: function (scope, element, attrs) {
            scope.options = Enums.query(function (result) { scope.options = result[scope.key]; });
        }
    };

}
]);

预期用法如下:

<label for="Application" class="control-label col-med-3 col">Application:</label>
                <select id="Application" class="form-control col-med-3 col pull-right">
                    <enum-options key="ApplicationType"></enum-options>
                </select>

然后会产生与我的c#枚举一致的所有选项。

在这种情况下,使用标记时似乎永远不会调用该指令。

请注意。我认为工厂工作正常,因为我可以将它注入一个单独的控制器,它按预期工作。

3 个答案:

答案 0 :(得分:1)

1)我猜 projMgrApp 是主要模块。您是否已将enumService作为依赖项包含在此模块中?

angular.module('projMgrApp',['enumServices'])

否则您的主模块将不会知道您的服务是否存在。

2)您是否了解如何声明和使用指令。当你宣布

projMgrApp.directive('EnumOptions', ['Enums', function (Enums) {}])

实际上应该在html代码中使用:

<enum-options></enum-options>

我不太确定这个名字,但它应该以小写字母开头,例如 enumOptions

3)我不知道你为什么使用这个键作为属性。你根本不处理它。 scope.key不起作用。您必须解析链接函数(link: function(scope, element, attributes))中的属性或为指令创建隔离范围。

将以下内容添加为返回对象的属性:

scope : {
  key:'@' //here depends if you want to take it as a string or you will set a scope variable.
}

完成后,您可以像在链接函数中一样使用它(scope.key)。

修改

这是一个类似的工作版本(优化不使用http调用)到你想要实现的目标。告诉我,如果我错过任何东西。 Working example

答案 1 :(得分:0)

如果您收到baddir错误,请尝试根据doc将您的指令名重命名为enumOptions(不要忘记注射):

 This error occurs when the name of a directive is not valid.

 Directives must start with a lowercase character and must not contain leading or trailing whitespaces.

答案 2 :(得分:0)

感谢Tek的建议,我能够按照预期使其完全正常运行。这意味着现在我的angularJS + HTML选择标签/指令完全绑定到我的API枚举。我知道我需要根据用户反馈调整添加到这些内容的行,而且我使用这些枚举来表示应用程序中的强类型数据。因此,它将节省大量时间并有助于减少代码重复。感谢所有帮助过的人!

我使用的服务和指令在下面复制,以防其他人开始使用Angular遇到类似问题或有类似要求。

服务:

(function () {
'use strict';

var enumService = angular.module('enumService', [])

.service('Enums', ['$http', '$q', function ($http, $q) {
    return {
        fetch: function () {
            var defer = $q.defer();
            var promise = $http.get("/api/Enums").then(function (result) {
                defer.resolve(result);
            });
            return defer.promise;
        }
     }
 }]);})();

指令:

angular.module('projMgrApp').directive('enumOptions', ['Enums', function (Enums) {
    return {
        restrict: "EA",
        scope: {
            key: "@"
        },
        template: "<select><option ng-repeat='enum in enumIds' ng-bind='enum'></option><select>",
        link: function (scope) {
            Enums.fetch().then(function (result) {
                scope.enumIds = result.data[scope.key];
            });
        }
    };
}]);