AngularJS指令不在父作用域

时间:2015-05-11 19:41:17

标签: angularjs angularjs-directive angularjs-scope single-page-application

我有一个指令,其中包含一个带有鼠标右键单击事件的图像,该事件显示自定义上下文菜单。当用户单击此上下文菜单中的项目时,我想在父控制器上调用方法。我已经使用Ian Walter ng-context-menu设置了上下文菜单。当我单击上下文菜单项时,我会调用指令中的代码。但是,我所尝试的一切都无法调用控制器的功能。我确信只有一些我忘记分配的内容,因为我是Angular的新手。

主视图调用指令如下:

<div id="apptOverlay" ng-controller="apptCtrl as apptCtrl">
  <div class="apptList">
    <section data-ng-repeat="apptItem in apptCtrl.appointmentList" data-ng-model="apptCtrl.appointmentList" class="apptStaffList">
      <my-box appt="apptItem" status-list="apptCtrl.statusList" edit-appt="apptCtrl.editAppt(apptItem)" status-changed="apptCtrl.statusChanged(apptItem)"></my-box>
    </section>
  </div>
</div>

指令的HTML如下:

<section>
    <header>
        <img src="../../images/{{ appt.StatusIcon }}" data-context-menu context-menu-margin-bottom="10" data-target="menu-{{ appt.Id }}" />
        <div id="menu-{{ appt.Id }}" class="dropdown position-fixed">
            <ul class="dropdown-menu" role="menu">
                <li data-ng-repeat="status in statusList" >
                    <a id="status-{{ status.StatusId }}" data-ng-click="changeStatus(this)">
                        <img title="{{ status.StatusDescription }}" alt="{{ status.StatusDescription }}" src="../../images/{{ status.Icon }}" class="cellImage cellImageSmall" />
                        {{ status.StatusDescription }}
                    </a>
                </li>
            </ul>
        </div>
        {{ appt.LastName }}, {{ appt.FirstName }} 
    </header>
    <article>
        <ul>
            <li>Comments: {{ appt.Comment }}</li>
        </ul>
    </article>
</section>

该指令的代码包括以下内容:

angular.module('app').directive('myBox', ['$parse', function ($parse) {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            appt: '=appt',
            editAppt: '&',
            statusList: '=',
            statusChanged: '&'
        },
        templateUrl: 'myBox.html',
        controller: function($scope) {
          $scope.changeStatus = function (item) {
              $scope.appt.CurrentStatusId = item.status.StatusId;
              $scope.statusChanged({ appointment: $scope.appt });
          };
        }
    };
}]);

控制器包括以下内容:

angular.module('app').controller('apptCtrl', ['$scope', function($scope) {
    var self = this;
    self.appointmentList = [];
    self.statusList = [];

    self.changeStatus = function (appointment) {
        var id = appointment.Id;
    };
}]);

顺便说一句,我在指令中有一个双击方法,它可以在父控制器中调用一个函数而没有任何问题,但是在$ elem.on中使用$ scope。$ apply()(&#39; dblclick&#39;)方法。当我尝试在我的指令的changeStatus函数中调用$ scope。$ apply()时,它会给我一个正在进行的&#39; $ apply&#39;错误。

我已将此代码包含在此Plunkr中。因为它是一个更大的项目的一部分,我试图只提取这个问题的重要部分。我试过在控制器和链接部分调用指令函数具有相同的结果。我知道上下文菜单在Plunk中没有很好地显示,但是并不认为CSS对这个问题很重要。

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

使用$ emit / $

http://plnkr.co/edit/WU54jP

   angular.module('app').directive('myBox', ['$parse', function ($parse) {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            appt: '=appt',
            editAppt: '&',
            statusList: '=',
            statusChanged: '&'
        },
        templateUrl: 'myBox.html',
        controller: function($scope) {
          $scope.changeStatus = function (item) {
              $scope.appt.CurrentStatusId = item.status.StatusId;
              $scope.statusChanged({ appointment: $scope.appt });
              $scope.$emit('changeStatus', 'Look Ma, No Hands');
             // alert('Status changed in directive');
            };
        },
        link: function ($scope, $elem, $attr) {

            $elem.bind('dblclick', function () {
                $scope.editAppt($scope.appt);
            });

            $elem.on('dblclick', function () {
                // Need to do this to set the appointment in the edit box
                $scope.$apply();
            });

            ////var fnChangeStatus = $parse($attr.statusChanged);
            //$scope.changeStatus = function (item) {
                //$scope.appt.StatusId = item.status.StatusId;
                //$scope.statusChanged({ appointment: $scope.appt });
                //alert('Status changed in directive');
                ////fnChangeStatus({ appointment: $scope.appt });
            //};

            var drawBox = function () {
                $elem.css({
                    height: '150px',
                    backgroundColor: '#99ccff'
                });
            };

            drawBox();
        }
    };
}]);


angular.module('app').controller('mainCtrl', function($scope){
 // There is a main controller that has more general code for the entire application
});

angular.module('app').controller('apptCtrl', ['$scope', function($scope) {
    /****************************************************************************************************
        Properties
    *****************************************************************************************************/
    var self = this;
    self.appointmentList = [{Id: 1, Comment: 'Testing...', LastName: 'Test', FirstName: 'First', StatusId: 1, StatusIcon: 'Scheduled.png'}];
    self.statusList = [{StatusId: 1, Icon: 'scheduled.jpg', StatusDescription: 'Scheduled'}, {StatusId: 2, Icon: 'cancelled.jpg', StatusDescription: 'Cancelled'}];

    /****************************************************************************************************
        Methods
    *****************************************************************************************************/
    self.editAppt = function (appointment) {
        self.action = 'Edit';
        // editing appointment here...
        alert('Editing box in controller');
    };
    $scope.$on('changeStatus', function (event, data) {
      alert(data);
    });

    self.changeStatus = function (appointment) {
        var id = appointment.Id;
        // changing status here...
        alert('Changing status in controller');
    };
}]);

解释:http://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/