在name参数上传入$ scope。$作为AngularJS指令的属性

时间:2017-04-25 21:04:48

标签: javascript angularjs

我正在尝试创建一个指令,允许我传入一个属性字符串,然后在使用$ scope。$ on订阅事件时将其用作“name”参数。基本上,一系列事件是这样的:

  1. 使用$ rootScope广播对象。$ broadcast称为'validationResultMessage',例如在另一个控制器中。
  2. 我有一个指令,它有一个名为“subscription”的属性,我将字符串'validationResultMessage'传递给它。
  3. 该指令将“subscription”属性的值传递给其范围,并使用“$ scope。$ on”订阅它。
  4. 问题是,在评估所有内容时,属性的值似乎是“未定义的”,因此当我尝试使用$ scope。$ on进行订阅时,它实际上将我订阅为“undefined”而不是“validationResultMessage”

    这是我的指示:

    app.directive('detailPane', function () {
    return {
        restrict: 'E',
        scope: {
            selectedItem: '=',
            subscription: '@',
        },
        templateUrl: 'app/templates/DetailPane.html',  //I'm also worried that this is causing my controller to get instantiated twice
        controller: 'DetailPaneController'
    
      };
    });
    

    然后我这样使用:

    <td class="sidebar" ng-controller="DetailPaneController"  ng-style="{ 'display': sidebarDisplay }">
                <detail-pane 
                        selected-item='validationResult'
                        subscription='validationResultMessage'/>
    
    </td>
    

    我试图将此属性传递给控制器​​:

    app.controller('DetailPaneController', ['$scope', '$http', 'dataService', 'toastr', '$uibModal', '$rootScope', '$attrs', function ($scope, $http, dataService, toastr, $uibModal, $rootScope, $attrs) {
    $scope.fetching = [];
    $scope.validationResult = null;
    $scope.sidebarDisplay = 'block';
    
    
    
    console.log('subscription is ', $scope.subscription);
    var thisSubscription = $scope.subscription;
    
    //if I hardcode the param as 'validationResultMessage', this works
    $scope.$on($scope.subscription, function (event, arg) {
        $scope.validationResult = arg;
        });
    }]);
    

3 个答案:

答案 0 :(得分:2)

因此,我设法解决此特定问题的另一种方法是仅使用指令体中定义的内部DetailPaneController。我的一部分问题是我通过在html中使用ng-controller=作为父控制器以及在指令体中定义来使控制器实例化两次。这样我就可以直接使用&#34; @&#34;绑定,一切都按正确的顺序解决。我甚至可以在我的模板中有另一个指令,我可以将validationResult传递给。{/ p>

新设置如下所示:

<强> DetailPaneController:

app.controller('DetailPaneController', ['$scope', '$http', function ($scope, $http) {

$scope.$on($scope.subscription, function (event, arg) {
    $scope.validationResult = arg;
    $scope.exception = JSON.parse(arg.Exception);
    });
}]);

DetailPane指令:

app.directive('detailPane', function () {
return {
    restrict: 'E',
    scope: {
        subscription: '@' //notice I am no longer binding to validationResult
    },
    templateUrl: 'app/templates/DetailPane.html',
    controller: 'DetailPaneController'
    };
});

HTML中使用的指令:

        <div class="sidebar" ng-style="{ 'display': sidebarDisplay }">
            <detail-pane subscription='validationResultMessage' />
        </div>

指令模板(为了更好的衡量标准):

<div class="well sidebar-container">
<h3>Details</h3>
<div ng-show="validationResult == null" style="padding: 15px 0 0 15px;">
    <h5 class=""><i class="fa fa-exclamation-triangle" aria-hidden="true" /> Select a break to view</h5>

</div>
<div ng-show="validationResult != null">
    <table class="table table-striped">
        <tr ng-repeat="(key, value) in validationResult">
            <td class="sidebar-labels">{{key | someFilter}}</td>
            <td >{{value | someOtherFilter : key}}</td>
        </tr>
    </table>
    <another-directive selected-item="validationResult" endpoint="endpoint" />
</div>

答案 1 :(得分:1)

我将发布我的答案第一,鉴于它是一些代码,请告诉我这是否是必需的结果,所以我可以提供意见。您应该能够运行提供的代码段。

&#13;
&#13;
var app = angular.module('myApp', []);

app.directive('detailPane', function() {
  return {
    restrict: 'E',
    transclude: false,
    scope: {
      selectedItem: '=',
      subscription: '@'
    },
    link: function(scope, elem, attr) {
      scope.$on(scope.subscription, function(e, data) {
        scope.selectedItem = data.result;
        elem.text(data.message);
      });
    },
  };
});

app.controller('DetailPaneController', function($scope) {
  $scope.validationResult1 = "";
  $scope.validationResult2 = "";
});

app.controller('SecondController', function($rootScope, $scope, $timeout) {

  $timeout(function() {
    $rootScope.$broadcast('validationResultMessage1', {
      message: 'You fail!',
      result: 'Result from 1st fail'
    })
  }, 2000);

  $timeout(function() {
    $rootScope.$broadcast('validationResultMessage2', {
      message: 'You also fail 2!',
      result: 'Result from 2nd fail'
    })
  }, 4000);

});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app='myApp'>
  <div ng-controller="DetailPaneController">
    <detail-pane class='hello' selected-item='validationResult1' subscription='validationResultMessage1'></detail-pane>
    <br/>
    <detail-pane class='hello' selected-item='validationResult2' subscription='validationResultMessage2'></detail-pane>

    <hr/>
    <span>{{validationResult1}}</span>
    <br/>
    <span>{{validationResult2}}</span>

  </div>
  <div ng-controller="SecondController">

  </div>
</body>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

我认为您应该在$ scope.subscription上设置观察者并检查是否设置了新值,然后开始订阅传递的事件。

$scope.$watch('subscription', function(nv, ov){
 //this makes sure it won't trigger at initialization
 if(nv!==ov){
   $scope.$on($scope.subscription, function (event, arg) {
      $scope.validationResult = arg;
   });
 }
});