将数据从指令传递给兄弟DOM的正确方法是什么?

时间:2015-06-11 06:46:00

标签: jquery angularjs

出于动画原因,我将指令及其值分隔在不同的HTML元素中。

当指令加载时,分离的元素需要从指令更新。如何将directive中的信息传递给具有相同controller的其他HTML元素?

示例:

<div class="progName">
    <program-name app-name="appName" index='{{$index}}' ng-repeat="appName in appNames"></program-name> 
    <!-- the first directive as active one then.. -->
</div>

<div>Some other details goes here</div>
<div class="percent">
    {{appName.percent}}
    <!-- how to pass here -->
</div> 
<div>
    some footer information
</div>

在我的场景中,每当用户点击指令时,{{appName.percent}}需要更新指令。

如果我不清楚,请发表评论。

Live Demo

3 个答案:

答案 0 :(得分:2)

假设您希望在DOM树中作为兄弟姐妹的两个指令(传递数据)之间进行通信。

如果两个指令在DOM树中不在父子关系中并且您需要在它们之间进行通信,则可以使用$ rootScope。并从$ rootScope广播一个事件,并在另一个指令中接收该事件。

只需在一个指令中(您要从中发送数据)注入$ rootScope并使用

$rootScope.$broadcast("eventName",attrs.valueYouWantToPass);

然后在另一个指令(您希望接收传递数据)上,您必须解决此事件。只需使用以下代码段:

scope.$on('eventName', function (event, valueThatPassed) {
   //use this valueThatPassed to do what you want to do
   event.stopPropagation(); //stop the propagation so that the event doesn't propagate further
});

检查你的小提琴后。我简化了它。我已经删除了其他不需要的代码来显示解决您确切的问题。我刚刚把它改成了一个新的小提琴,它用指令的click事件上的appName.percent值改变你的指令元素的值。请检查以下小提琴。

http://jsfiddle.net/obzy8s22/

答案 1 :(得分:1)

如果需要绑定控制器的百分比,请为其添加双向数据绑定,以便每个指令可以直接访问它:

.directive('programName', function ($compile) {
return {
    restrict: 'AE',
    replace: true,
    scope: {
        appName: '=',
        index: '@',
        percent: '='
    },
    link: function (scope, element, attr) {
        var getTemplate = function (index) {
            return Number(index) ? '<h2 class="que t{{index}}" ng-click=callMe()>{{appName.name}} {{appName.company}}{{appName.percent}}</h2>' : '<h2 class="active que t{{index}}" ng-click=callMe()>{{appName.name}}arif {{appName.company}}{{appName.percent}}</h2>';
        }
        element.html(getTemplate(scope.index));
        $compile(element.contents())(scope);
    },
    controller: function ($scope) {
        $scope.callMe = function () {
            $scope.percent = $scope.appName.percent;
        }
    }
}

并添加相应的属性:

<program-name app-name="appName" index='{{$index}}'
  ng-repeat="appName in appNames" percent="data.percent">
</program-name>

控制器只是定义对象内的percent值,因此名称不会与子范围冲突:

.controller('MainCtrl', function ($scope) {
  $scope.appNames = [/* ... */];
  $scope.data = {
    percent: 22
  };
}

我强烈反对使用$rootScope,因为双向通信避免了所有这些消息处理及其引入的耦合。

Live demo

答案 2 :(得分:0)

创建一个服务来保存数据并在两个指令上都需要服务。然后您可以随时访问数据而不传递数据。该服务可以在需要时通知指令。

app.service('shareData', function () {
  var UPDATE_EVENT = 'update',
  var REMOVE_EVENT = 'remove', 
  var listeners = {};
  var data = {};
  return {
    on: function (eventName, callback) {
      if (listeners.hasOwnProperty(eventName)) {
        listeners[eventName].push(callback);
      } else {
       listeners[eventName] = [callback];
      }
    },
    set: function () {
      if (arguments.length > 1) {
        data[arguments[0]] = arguments[1];
        notify(UPDATE_EVENT + '.' + arguments[0]);
      }

      if (arguments.length === 1) {
        data = arguments[0];
        notify(UPDATE_EVENT);
      }

      if (arguments.length < 1) {
        throw new Error('set method requires at least one parameter');
      }
    }
  };

  function notify (eventName) {
    if (!listeners.hasOwnProperty(eventName)) {
      throw new Error('No such event registered' + eventName );
    }

    for (var i = 0; i < listeners[eventName]; i++) {
     listeners[eventName][i]();
    } 
  } 

})
.directive('firstDirective'['shareData', function (shareData){
  return {
   link: function (scope, element, attrs, ctrl) {
     shareData.on('update', function () {
       // Do your stuff
     });
   }
  };

}])
.directive('secondDirective'['shareData', function (shareData){
  return {
   link: function (scope, element, attrs, ctrl) {
     element.bind('click', fucntion () {
       shareData.set({
         // change your data
       });
     });

   }
  };

}]);

Demo