Share data from a directive within another isolate

2019-08-03 17:50发布

问题:

I'm trying to take a component approach to my Angular code by writing component style directives, but I have run into a problem. Below is my html template for the page. Note that I'm using the AngularStrap tabs directive.

The problem I'm having is that the woSamplesSummary.materialsCount is undefined right under the work-order directive (outside of the tab pane scope), but it displays correctly in the tab pane directive as part of the tab title (within the tab pane scope). So the basic issue is how to share data on a page when using a directive within another isolated scope directive?

<work-order wo-id="{{woId}}"></work-order>
<div>Materials Count: {{woSamplesSummary.materialsCount}}</div>

<!--- TABS ------>
<div ng-show="woId" bs-tabs>

    <!--- MATERIALS --->
    <div bs-pane title="Materials ({{woSamplesSummary.materialsCount}})" id="materials">

        <work-order-samples 
            wo-id="{{woId}}" 
            wo-samples-summary="woSamplesSummary" >
        </work-order-samples>
    </div>

    <!--- additional tabs not shown --->

</div>

Here's my work-order-samples directive. I removed most of the logic, but you can see that I setup woSamplesSummary with two-way binding and have bound the properties to the controller, which is all working correctly and has allowed me to move away from using $scope.

.directive('workOrderSamples', function () {
    return {
        restrict: 'E',
        replace: 'false',
        templateUrl: 'myTemplate',
        scope: { },
        controllerAs: 'wosamplesCtlr',
        bindToController: {
            woId: '@',
            woSamplesSummary: '='
        },
        controller: function ($scope, $element, $attrs, myModel) {
            var self = this;
            $attrs.$observe('woId', function(woId) {
                workOrderSamples.find(conditions).then(function () {
                    self.woSamples          = workOrderSamples;
                    self.woSamplesSummary   = {
                        batchCount: workOrderSamples.batches.length,
                        materialsCount: workOrderSamples.list.length }
                });
            });
        }
    };
})

So the problem seems to be that the tabs directive is creating an isolated scope, so I am not able to make the data available outside of the tab I'm in.

It seems like there should be a way to make data available from a directive when it's used within other isolated scope directives. I've tried many different approaches, but without any success. Assigning the value to $rootScope within my directive does work, but it's just not a good solution (e.g. - if I want to use this directive multiple times on a page).

Any ideas?

回答1:

There are two ways of communication in Angular. One of which is to use services. The other is to use $broadcast and $emit/$on.

Angular Custom Events using $broadcast, $emit, $on.

In your directive I'd start with:

$rootScope.$broadcast('myEvent', data)

Then on the receiving end:

$rootScope.$on('myEvent', function(e, args){
   // do stuff
});

You must also unregister $rootScope listeners to avoid memory leaks. The way you do that is by calling the function that the $on returns and apply it during the scope's $destroy event.

var cleanfunction = $rootScope.$on('showLogin', showLoginDialog());

$scope.$on('$destroy', function(){
  cleanfunction();
})