Passing to $ scope. $ For name parameter as attribute of AngularJS directive

I'm trying to create a directive that allows me to pass an attribute string, which I then use as the "name" parameter when subscribing to events using $ scope. $ on. Basically, the series of events is as follows:

  • The object is broadcasted using $ rootScope. $ broadcast is called "validationResultMessage", for example in another controller.
  • I have a directive that has an attribute called "subscription" to which I pass the string "validationResultMessage".
  • This directive passes the value of the "subscribe" attribute to its scope and subscribes to it "$ scope. $ On".

The problem is that the value of the attribute is "undefined" at the time everything is evaluating and so when I try to subscribe using $ scope. $ on, it actually signs me to "undefined" and not "validationResultMessage"

Here is my directive:

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'

  };
});

      

which I then use like this:

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

</td>

      

And the controller I'm trying to pass this attribute to:

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


source to share


3 answers


I am going to post my 1st answer given that this is a bit of code, please let me know if this is a required result so I can provide comments. You should be able to run the provided code snippet.



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);

});
      

<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>
      

Run codeHide result


+1


source


So the other way I was able to solve this particular problem is to use only the inner DetailPaneController

one as defined in the directive body. Part of my problem was that I was causing the duplicate controller twice, having it both the parent controller using ng-controller=

in my html and being defined in the directive body. This way I can just use the "@" direct anchor and everything is resolved in the correct order. I may even have another directive in my template to pass mine validationResult

to.

The new setting looks like this:

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 directive:

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

      



Directive used in HTML:

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

      

Directive template (for a good mark):

<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>

      

+2


source


I think you should set the watcher to $ scope.subscription and check if a new value is set, then start subscribing to the passed event.

$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;
   });
 }
});

      

0


source







All Articles