【问题标题】:ng-hide is not getting updated dynamicallyng-hide 没有动态更新
【发布时间】:2018-01-05 13:57:20
【问题描述】:

我有下面带有 nghide 的 div 元素

 <div ng-hide="showdiv" class="btnshowall"> 
    <a class="button button-block round outline"
       style="background: transparent !important;" >
      Show All
    </a>
 </div>

和控制器如下

.controller('mapCtrl', ['$scope', '$stateParams','User','$cordovaGeolocation','geoFireFac','GoogleMapFac','ConnectivityMonitor','PhysioFac','User',
function ($scope, $stateParams,User,$cordovaGeolocation,geoFireFac,GoogleMapFac,ConnectivityMonitor,PhysioFac,User) {

    console.log('called mapctrl');  
    GoogleMapFac.setUserLoc($scope.map);
    $scope.showdiv = User.getShowDiv();


}])

和用户服务作为

.service('User', ['ToastFac',function(ToastFac){
    return {
         showDiv : false,
        changeShowDiv : function(){
            console.log('in changeShowDiv before change '+this.showDiv);
            this.showDiv = !this.showDiv;
            console.log('in changeShowDiv after change '+this.showDiv);

        },

        getShowDiv : function(){
            return this.showDiv;
        }

我正在从谷歌地图的标记点击事件中调用 User.changeShowDiv(),如下所示

google.maps.event.addListener(marker, 'click', function () {
      alert('store id '+marker.get('store_id'));
      if(User.showDiv){
          console.log('in if');
          User.changeShowDiv();
          console.log('User.showDiv '+User.showDiv);
      }
      else{
          console.log('in else');
          User.changeShowDiv();
          console.log('User.showDiv '+User.showDiv);
      }

});

日志按预期出现

in else
services.js:123 in changeShowDiv before change false
services.js:125 in changeShowDiv after change true
services.js:218 User.showDiv true
services.js:211 in if
services.js:123 in changeShowDiv before change true
services.js:125 in changeShowDiv after change false
services.js:213 User.showDiv false
services.js:216 in else
services.js:123 in changeShowDiv before change false
services.js:125 in changeShowDiv after change true
services.js:218 User.showDiv true

默认情况下,由于 User.showDiv 变量为 false,showAll 按钮是可见的。但是按钮并没有被标记点击事件隐藏和到来。

有人可以指导我缺少什么。

【问题讨论】:

    标签: javascript html angularjs google-maps ionic-framework


    【解决方案1】:

    您只从User.getShowDiv 方法中检索值一次。但是当它发生变化时,您不会更新 showdiv 范围变量。要每次更新值,您可以直接将User.getShowDiv 方法的引用绑定到showdiv 范围变量,如下所示

    $scope.showdiv = User.getShowDiv; 
    

    在 HTML 上调用 showdiv 方法之后,该方法最终将评估每个摘要循环的值,这与其他 bindings 不同。

    ng-hide="showdiv()"
    

    即使以上也不能解决您的问题。基本上,您正在从外部上下文 Angular 更新一些变量,即 click 事件。因此,您必须在从 click 事件侦听器运行更新值后立即手动运行摘要循环。只需使用$timeout(angular.noop) 安全地启动摘要循环即可。

    google.maps.event.addListener(marker, 'click', function () {
          alert('store id '+marker.get('store_id'));
          if(User.showDiv){
              //Code here
          }
          else{
              //Code here
          }
          //manually triggering digest loop to make binding in sync
          $timeout(angular.noop); //It will run new digest cycle.
    });
    

    【讨论】:

    • 我试过这个。不幸的是,我失去了默认行为。我错过了一些东西。你能在这个小提琴中纠正我吗? jsfiddle.net/25kkvfdt/3
    • @kpvsrkp 给我第二个,更新我的答案:) 我意识到我错过了添加的一个关键点
    • @kpvsrkp 检查更新的答案。即使你可以参考 georgeawg 的答案。我们都有相同的东西.. :)
    【解决方案2】:

    来自AngularJS框架之外的事件需要通过$apply引入到AngularJS框架中:

    google.maps.event.addListener(marker, 'click', function () {
          alert('store id '+marker.get('store_id'));
          if(User.showDiv){
              console.log('in if');
              User.changeShowDiv();
              console.log('User.showDiv '+User.showDiv);
          }
          else{
              console.log('in else');
              User.changeShowDiv();
              console.log('User.showDiv '+User.showDiv);
          }
          //IMPORTANT
          $scope.$apply();    
    });
    

    AngularJS 通过提供自己的事件处理循环来修改正常的 JavaScript 流程。这将 JavaScript 拆分为经典和 AngularJS 执行上下文。只有在 AngularJS 执行上下文中应用的操作才能受益于 AngularJS 数据绑定、异常处理、属性监视等……您也可以使用 $apply() 从 JavaScript 进入 AngularJS 执行上下文。请记住,在大多数地方(控制器、服务)$apply 已经被处理事件的指令调用。只有在实现自定义事件回调或使用第三方库回调时,才需要显式调用 $apply

    — AngularJS Developer Guide - Integration with the browser event loop


    一定要修复ng-hide和控制器:

    <div ng-hide="showdiv()" class="btnshowall">
    
    $scope.showdiv = function() {
        return User.getShowDiv();
    };
    

    在上面的代码中,ng-hide 指令将在每个摘要周期执行showdiv() 函数并相应地更新元素的可见性。

    【讨论】:

    • 很棒的 +1。傻我:(,我错过了这一点,当我看到你在帖子上的编辑时我才意识到这件事:)你一如既往的棒:)
    • 很明显该事件来自AngularJS框架之外。 $evalAsync 更多地用于从 AngularJS 执行上下文中调度异步操作。
    • @Hadi $evalAsync/$apply/$timeout 在这里与我们从 AngularJS 外部世界手动运行事件具有相同的含义。但是是的,为了安全起见,我们应该使用$evalAsync$timeout
    • 感谢您的回复。 @PankajParkar 和 georgeawg
    • 请注意$timeout 将导致额外的浏览器渲染周期和额外的 $digest 周期。在这种情况下没有必要,但一些程序员这样做是为了“安全”。
    猜你喜欢
    • 2016-01-12
    • 2017-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 2014-10-14
    • 2016-03-11
    • 1970-01-01
    相关资源
    最近更新 更多