【问题标题】:ng-show / ng-hide / ng-if don't work on Angular directiveng-show / ng-hide / ng-if 不适用于 Angular 指令
【发布时间】:2016-03-07 20:57:07
【问题描述】:

我正在构建一个采用卡片形式的指令。当我加载卡片模板时,如果用户之前隐藏了卡片,我想确保卡片是隐藏的。我可以通过request.hide 属性跟踪这个。

这是我的指令(准系统):

app.directive('request', ['$http', '$timeout', function($http, $timeout) {
    return {
        replace: true,
        templateUrl: '/assets/request.html',
        transclude: false,
        scope: {
            request: '='
        },
        controller: ['$scope', '$http', '$timeout', function($scope, $http, $timeout) {
            // Cool stuff goes in here
        }]
    };
}]);

这是我的模板:

<div>
    <div ng-hide"request.hide" class="card">
        <!-- Cool stuff goes in here -->
    </div>
</div>

当页面加载时,每个request 都有一个hide 属性。理论上,当我调用我的指令时,如果hide === true 应该隐藏它。不幸的是,情况似乎并非如此。无论我尝试什么,我都无法在初始化时隐藏我的指令。我尝试在根元素上使用ng-hide="request.hide"ng-show="!request.hide"ng-if="!request.hide",但没有任何效果。

我想知道这些指令是否不适用于自定义指令的根元素,因此我尝试将我的指令包装在一个额外的 div 中并使用 ng-hideng-showng-if on .card div,现在是子元素,但也没有效果。

似乎ng-hide 根本没有被评估,或者在request 被定义在指令的范围之前被评估。

【问题讨论】:

  • 应该可以正常工作。显示request 对象的示例。一个简单的演示也会有所帮助。
  • 您确定您的请求对象的属性设置正确吗?尝试使用ng-hide="true" 看看是否隐藏它
  • 在controller函数中,记录$scope.request的值,看是否有hide属性。

标签: javascript angularjs angular-ng-if ng-hide


【解决方案1】:

您提供的模板标记中有一个小错字,在 ng-hide 后缺少一个 = 符号。但我猜这只是你写问题时的一个错字。

否则,指令代码看起来很好,它应该可以工作。您应该仔细检查您将指令绑定到的“请求”对象,并确保 hide 属性实际上是一个布尔值,而不是一个字符串。

ng-if、ng-show 和 ng-hide 都设置了观察者,因此问题不应该是在填充范围之前对表达式进行评估。

仅出于测试目的,请尝试在指令控制器中的作用域上设置布尔值,然后进行隐藏或反之。

【讨论】:

  • 我试过了,没有效果。我尝试将ng-showng-if 绑定到hide,其中$scope.hide = $scope.request.hide。我还检查以确保 request.hide 是布尔值,而不是字符串。如果我绑定到hide 而不是request.hide,我的所有指令都将被隐藏,而不仅仅是hide === true 的指令。
  • 这是一个指令的 plunker 示例,该指令根据传递给它的“请求”对象隐藏其内容。只需将控制器中的值从 true 切换为 false 即可查看显示和隐藏 plnkr.co/edit/3WtwSIBtDYPQ9QkRecrO?p=preview 的指令
  • 你的指令做了它应该做的事情,但我想知道问题是否在于我的指令异步加载模板,而你的指令的模板在页面加载时可用。在我的代码中,我已经尝试将hg-hide/ng-show/ng-if 绑定到$scope.hide,然后我在控制器的第一行定义了它,但它没有任何区别。当我将定义包装在 $timeout 中时,它起作用了,这似乎表明我的表达式第一次没有被评估。
  • 嗨,我更新了 plunker 以更接近您的情况。模板和请求数据都是异步加载的。尽管如此,指令的模板直接绑定到它的作用域,你可以看到它隐藏了(尽管在发出数据请求时有一个闪烁.. ng-cloak 是针对这个闪烁问题的)。该指令甚至不会在其模板解析之前尝试呈现,并且当父控制器更新其数据时,更改会向下传播到指令。你能试试吗? plnkr.co/edit/cCELNPLIEyHVJmIN0lbc?p=preview
  • 这个 pluncker 也可以正常工作,但是如果没有 $timeout 块,我仍然无法让它在我的应用程序中工作。一定还有其他一些我遗漏的混杂因素在这里没有体现。很难确定,因为我的应用程序非常复杂。无论如何,既然我得到了一个与 $timeout 合作的 hacky 修复程序,我几乎已经放弃了解决根本问题。
【解决方案2】:

尝试在包装器上使用ngCloak-div。只要 angular 仍在评估事物,它就应该隐藏 div 及其子项。

https://docs.angularjs.org/api/ng/directive/ngCloak

编辑: 实际上,没有。 ngCloak 不像我记得的那样工作。它隐藏了元素及其所有子元素,但前提是它没有在编译阶段遇到——这对我来说还为时过早。不过,您可以编写自己的伪装指令。

这里是ngCloak's 来源:

var ngCloakDirective = ngDirective({
  compile: function(element, attr) {
    attr.$set('ngCloak', undefined);
    element.removeClass('ng-cloak');
  }
});

您需要在链接前/链接后阶段模仿其行为。

【讨论】:

  • 我认为我对前/后链接阶段的理解不够深入,无法编写自己的ngCloak 版本。我开箱即用地尝试了它,看看它是否有帮助,但它对我没有任何改变。我确信问题的根源在于该指令没有在编译时评估ng-show/ng-hide/ng-if
【解决方案3】:

ng-show 可能不可靠。

<div>
    <div ng-show"!!request.hide" class="card">
        <!-- Cool stuff goes in here -->
    </div>
</div>

【讨论】:

  • 如果您阅读我的问题,您会注意到我已经尝试过ng-if
  • 您使用的是哪个版本的 Angular?理想情况下,您为什么不直接在新自定义指令的父 div 上设置显示隐藏,因为您在请求中传递它?
  • 1.2.18。指令的父 div 包含其他我不想隐藏的不相关指令。
【解决方案4】:

我终于想出了解决问题的方法,但我仍然想知道导致问题的原因以及解决问题的最佳方法。

我有一个理论认为,当我的指令被编译时,ng-show/ng-hide/ng-if 没有被评估,所以我决定像以前一样在我的指令的根元素上使用ng-hide="hide",但在我的控制器中,而不是立即设置$scope.hide = $scope.request.hide,我决定将其移动到$timeout 块内,延迟10ms,如下所示:

$timeout(function() {
    $scope.hide = $scope.request.hide;
}, 10)

这会在编译指令后触发摘要循环,从而重新评估 ng-hide。延迟对于指令编译来说足够长,但对于用户来说也足够短。

【讨论】:

  • 你真的不需要用 ng-show、ng-hide 和 ng-if 来做这个摘要循环破解。正如我上面所说,这三个指令在它们给定的表达式上设置了观察者。您应该能够将 ng-hide 直接从指令的隔离范围绑定到视图。查看我上面提供的 plunker。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-19
  • 2014-12-30
  • 2014-12-08
  • 2014-03-27
  • 1970-01-01
  • 2016-10-06
  • 1970-01-01
相关资源
最近更新 更多