如何从指令模板访问Object.keys(object).length?

时间:2014-04-04 02:22:26

标签: angularjs angularjs-directive

我尝试创建一个指令,列出错误对象({phone: ["is required"]}中包含的所有错误,但仅当对象非空时才会列出。说"以下错误......"当没有错误时没有意义。)

通过测试Object.keys(errors).length,我想出了如何检查对象是否为空。 问题是我无法弄清楚如何从我的指令模板中访问Object.keys。这可能吗?

因为Angular表达式被评估" (在$parse的上下文中使用eval()而不是scope)而不是window的上下文中,我们无法访问Object之类的内容1}}来自指令模板,因为Object不是范围的属性。 (文件:Expressions

到目前为止有道理。它继续说"与JavaScript不同,其中名称默认为全局window属性,Angular表达式必须显式使用$window来引用全局window对象。例如,如果要在表达式中调用alert(),则必须使用$window.alert()

但即使我Object,我似乎无法访问$window.Object。我错过了什么?


这是我调试指令的代码(这里是jsfiddle):

app.js.coffee:

…
.directive 'displayErrorsAllKeys', ->
  {
    restrict: 'A',
    scope: {
      errors: '='
      debug: '@debug'
    }
    templateUrl: 'templates/display-errors-all-keys'
  }

.run(['$rootScope', ($rootScope) ->
  $rootScope.nonEmpty = (object) ->
    !! Object.keys(object).length
])

.controller('TestDisplayErrorsAllKeys',
['$scope',
( $scope ) ->

  $scope.other_errors = {}

  $scope.add_errors = ->
    $scope.other_errors = {"surname":["is required"],"phone":["is required"]}

  $scope.clear_errors = ->
    $scope.other_errors = {}
])

显示错误 - 全keys.ngt.haml:

.errors(ng-show="$window.Object.keys(errors).length > 0")
  %p The following errors prevented this from saving:
  %div(ng-repeat="(key, error_messages) in errors") {{key}}: {{error_messages | toSentence}}

test_ng_display-错误 - 全keys.html.haml

:scss
  .errors {
    color: red;
  }

%div(ng-app='MyApp')
  %form(ng-controller="TestDisplayErrorsAllKeys")
    %p errors: {{ other_errors }}
    %p nonEmpty(other_errors): {{ nonEmpty(other_errors) }}
    %hr/

    %div(display-errors-all-keys errors="other_errors")

    %input(type="button" value="Add errors" ng-click="add_errors()")/
    %input(type="button" value="Clear errors" ng-click="clear_errors()")/

我终于通过在我的作用域中定义一个帮助器方法并调用它($root.nonEmpty(errors))(参见jsfiddle的工作演示)来实现它。

这可能是漂亮的好解决方案,但是:

  1. 有没有更好的方法来解决这个问题?你会怎么做(写成ng-show表达式)?

  2. 如何直接在Object.keys(errors).length ??

  3. 中使用ng-show让它工作?

2 个答案:

答案 0 :(得分:10)

我会在指令范围内提供辅助函数(它是隔离的)。通常通过为指令提供链接功能:

.directive('displayErrorsAllKeys', function() {
    return {
        restrict: 'A',
        scope: {
            errors: '=',
            debug: '@debug'
        },
        link: function (scope) {
            scope.errorsExists = function(object) {
                return object && Object.keys(object).length;
            };
        },
        templateUrl: 'templates/display-errors-all-keys'
    };
})

在根范围内放置逻辑和数据很少是一种好的做法。另请注意,我将函数命名为errorExists,它在实际表示错误时提供了som抽象。

关于第二个问题,您可以在链接功能中添加scope.Object = Object;,但不要!此类特定逻辑不属于您的模板。模板应该关注是否显示错误,但不是为什么

答案 1 :(得分:9)

这是我为解决此问题而添加的nonEmpty过滤器(JavaScript equivalent

.filter 'nonEmpty', ->
  (object) ->
    !! (object && Object.keys(object).length > 0)

试验:

%div {{ null | nonEmpty }} should be false
%div {{ { } | nonEmpty }} should be false
%div {{ {a: '1'} | nonEmpty }} should be true

上面示例中的ng-show条件可以简化为:

ng-show="errors | nonEmpty"

现在我可以轻松地重复使用此检查逻辑,而无需向我可能想要使用它的每个指令或控制器添加新方法。