$ scope传递有一个延迟

时间:2015-12-30 19:22:53

标签: javascript angularjs angularjs-directive angularjs-scope angular-broadcast

我为多种目的构建一个Angular弹出系统。它的工作方式是我有一个名为bitPopup的指令,其中三个变量被传递给(typeactiondata),如下所示:

的index.html

<bit-popup type="popup.type" action="popup.action" data="popup.data"></bit-popup>

popup.js

app.directive('bitPopup', function () {
  return {
    restrict: 'E',
    template: html,
    scope: {
      type: '=',
      action: '=',
      data: '='
    },
    [***]
  }
}

弹出控制器然后根据类型加载不同的指令:

popup.html (上面显示的HTML模板)

<div class="pop-up" ng-class="{visible: visible}" ng-switch="type">
  <bit-false-positive-popup ng-switch-when="falsePositive" type="type" action="action" data="data"></bit-false-positive-popup>
</div>

false_positives.js (包含bitFalsePositivePopup指令)

[...]
scope: {
  type: '=',
  action: '=',
  data: '='
}
[...]

然后bitFalsePositivePopup指令的html模板显示data的一些属性。

现在,我触发弹出窗口的方式如下:

  1. 从包含bitPopup指令的指令内的模板中,我将更改$scope.popup&#39; typeactiondata
  2. 我会$scope.$broadcast('showPopup');
  3. bitPopup指令会因$scope.$on('showPopup', [...]});而作出反应,并使弹出窗口可见。
  4. 现在这个奇怪的事情发生在它第一次尝试的时候(弹出窗口打开了正确的data信息),但是在第一次尝试之后它将显示前一个data尝试。

    现在甚至更奇怪的是,我尝试在第一次尝试时记录信息,我发现的是:

      在致电$scope.popup之前, $scope.$broadcast('showPopup'); index.html 会显示正确的信息。
    • $scope.data bitPopup指令显示null
    • $scope.databitFalsePositivePopup指令处显示正确的信息。

    第二次尝试:

      $scope.popup index.html 再次正确。
    • $scope.databitPopup指令处显示上一次尝试的信息
    • 同样适用于bitFalsePositivePopup指令。

    另一个奇怪的事情是,当我使用$scope.$apply()它确实正常工作时,只显示$apply already in progress错误。我知道在这种情况下我不应该使用$scope.$apply(),因为它是所有Angular事件。但是如果通过的范围总是落后一步呢?

    我开始做错了吗?

    修改

    由于amahfouz's answer我决定发布更多代码以便澄清。我遗漏了一些不重要的细节,以便更清楚地阅读。

    的index.html

    <div class="falsePositives" ng-controller="falsePositives">
      <i class="fa fa-minus color-red" ng-click="triggerPopup('falsePositive', 'delete', {detection: getDetection(row.detection, row.source), source: row.source, triggers: row.triggers, hash: row.hash, date: row.date})"></i>
      <i class="fa fa-pencil" ng-click="triggerPopup('falsePositive', 'edit', {detection: getDetection(row.detection, row.source), source: row.source, triggers: row.triggers, hash: row.hash, date: row.date})"></i>
    
      <bit-popup type="popup.type" action="popup.action" data="popup.data"></bit-popup>
    </div>
    

    index.js

    var app = require('ui/modules').get('apps/falsePositives');
    
    app.controller('falsePositives', function ($scope, $http, keyTools, bitbrainTools, stringTools) {
      function init() {
        $scope.getDetection = getDetection;
    
        $scope.popup = {
          type: null,
          action: null,
          data: null
        };
      }
    
      function getDetection(hash, source) {
        return {
          'ids': 'BitSensor/HTTP/CSRF',
          'name': 'CSRF Detection',
          'description': 'Cross domain POST, usually CSRF attack',
          'type': [
            'csrf'
          ],
          'severity': 1,
          'certainty': 1,
          'successful': false,
          'input': ['s'],
          'errors': []
        };
      }
    
      $scope.triggerPopup = function (type, action, data) {
        $scope.popup = {
          type: angular.copy(type),
          action: angular.copy(action),
          data: angular.copy(data)
        };
    
        test();
    
        $scope.$broadcast('showPopup');
      };
    
      function test() {
        console.log('$scope.popup: ', $scope.popup);
      }
    }
    

    popup.html

    <div class="pop-up-back" ng-click="hidePopup()" ng-class="{visible: visible}"></div>
    <div class="pop-up" ng-class="{visible: visible}" ng-switch="type">
      <bit-false-positive-popup ng-switch-when="falsePositive" type="type" action="action" data="data"></bit-false-positive-popup>
    </div>
    

    popup.js

    var app = require('ui/modules').get('apps/bitsensor/popup');
    
    app.directive('bitPopup', function () {
      return {
        restrict: 'E',
        template: html,
        scope: {
          type: '=',
          action: '=',
          data: '='
        },
        controller: function ($scope) {
          $scope.visible = false;
    
          $scope.$on('showPopup', function () {
            console.log('$scope.data: ', $scope.data);
            $scope.visible = true;
          });
    
          $scope.$on('hidePopup', function () {
            hidePopup();
          });
    
          function hidePopup() {
            $scope.visible = false;
          }
    
          $scope.hidePopup = hidePopup;
        }
      };
    });
    

    false_positives.js

    var app = require('ui/modules').get('apps/bitsensor/falsePositives');
    
    app.directive('bitFalsePositivePopup', function () {
      return {
        restrict: 'E',
        template: html,
        scope: {
          type: '=',
          action: '=',
          data: '='
        },
        controller: function ($scope, objectTools, bitbrainTools, keyTools) {
    
          function init() {
            console.log('$scope.data @ fp: ', $scope.data);
          }
    
          function hidePopup() {
            $scope.data = null;
            $scope.$emit('hidePopup');
          }
    
          $scope.$on('showPopup', function () {
            init();
          });
    
          init();
    
          $scope.hidePopup = hidePopup;
        }
      }
    }
    

2 个答案:

答案 0 :(得分:1)

如果没有剩下的代码,我只能猜测:您需要在显示弹出窗口时使用promise或使用$ apply服务来更改弹出窗口可见性。

答案 1 :(得分:0)

在$ timeout中围绕您的$ broadcast事件,如下所示:

$timeout(function() {
  $broadcast('eventName');
});

它将等待$ scope更新,然后将触发事件。