2017-01-30 4 views
0

Как передать директиву директивы дочернего атрибута или значение attr в родительскую директиву?передать директиву дочерних данных в родительскую директиву

Учитывая widget директиву с директивой in-viewport атрибутов, я хочу, чтобы обновить атрибут inView каждый раз, когда документ прокручивается, и передать обновленное значение родительской директивы widget:

<widget in-viewport></widget>

В директиве Viewport : принят в качестве атрибута родительской директивы "виджет"

angular.module('app').directive('inViewport', function() { 
    return { 
     restrict: 'A', 
     scope: false, // ensure scope is same as parents 
     link: function(scope, element, attr) { 
     angular.element(document).on('scroll', function() { 
      // I've tried binding it to attr and parent scope of "widget" directive 

      attr.inView = isElementInViewport(element); 
      scope.inView = isElementInViewport(element); 
     }); 
     } 
    }; 
    }); 

Widget Директива:

angular.module('app').directive('widget', function() { 
    return { 
     restrict: 'AE', 
     scope: { 
     inView: '=' 
     }, 
     transclude: false, 
     templateUrl: 'directives/widgets/widgets.tpl.html', 
     link: function(scope) { 
     console.log('In Viewport: ', scope.inView); // Null 
+0

что родительская директива? что такое детская директива? – DilumN

+0

Поскольку 'in-viewport' является атрибутом' widget', я думал, что 'widget' будет родительской директивой' in-viewport' – Growler

+0

настолько запутанной, насколько это может показаться, эти директивы являются братьями и сестрами, архитектурно говоря. – Claies

ответ

1

Вы можете открыть API в своей родительской директиве и использовать для доступа к этому свойству isolateScope().

Работает fiddle.

var app = angular.module("app",[]); 

app.directive("widget", function($rootScope){ 
     return { 
     template: "<div>Scroll this page and widget will update. Scroll Y: {{scrollPosY}}</div>", 
     scope: {}, // <-- Creating isolate scope on <widget>. This is REQUIRED. 
     controller: ['$scope', function DirContainerController($scope) { 
     $scope.scrollPosY = 0; 
     // Creating an update function. 
     $scope.update = function(position) { 
      $scope.scrollPosY = position; 
      $scope.$digest(); 
     }; 
     }], 
    } 
}); 

app.directive("inViewport", function($window, $timeout, $rootScope){ 
     return { 
     restrict: 'A', 
     link:function(scope, element, attrs, parentCtrl){ 
     // Get the scope. This can be any directive. 
     var parentScope = element.isolateScope(); 
     angular.element(document).on('scroll', function() { 
      // As long as the parent directive implements an 'update()' function this will work. 
      parentScope.update($window.scrollY); 
      console.log('parentScope: ', parentScope); 
     }); 
     } 
    } 
}); 
+0

Re "Не уверен, почему вы хотите, чтобы inView как параметр с 2-сторонними параметрами, но здесь идет" - то, что я действительно хочу, является многоразовым методом, где я могу сказать, сможет ли какой-либо виджет с прикрепленной службой inViewport узнать, а не в виде viewport на прокрутке. – Growler

+0

Если это так, я считаю, что это ответ. Вы пробовали скрипку? – Ynot

+0

Ох, я получилчу. Вам нужна директива, которая будет работать для разных видов виджетов. Извините, не получил его в первый раз. – Ynot

1

Вот как вы можете получить доступ к родительским директивные переменные,

angular.module('myApp', []).directive('widget', function() { 
    return { 
     restrict: 'E', 
     template: '<viewport in-view="variable"></viewport> <h1>{{variable}}</h1>', 
     link: function(scope, iAttrs) { 

      scope.variable = 10; 
     } 
    } 
}).directive('viewport', function() { 
    return { 
     restrict: 'E', 
     scope: { 
       inView: "=", 
      }, 
     template: '<button ng-click="click()">Directive</button>', 
     link: function(scope, iElement, iAttrs) { 
         scope.click = function() { 
       scope.inView++; 
      } 
     } 
    } 
}); 

HTML

<div ng-app="myApp" ng-controller="Ctrl1"> 
    <widget></widget> 
</div> 

Здесь работает jsfiddle http://jsfiddle.net/p75DS/784/

Если у вас есть Цюй estion, спросите в поле комментария

1

Вот рабочая скрипку, используя структуру директивы: http://jsfiddle.net/ADukg/9591/

Markup как это:

<div ng-controller="MyCtrl" style="height: 1200px;"> 
    {{name}} 
    <hr> 
    <widget in-viewport></widget> 
</div> 

Просто прокручивать окно, чтобы вызвать событие. Обратите внимание, что родитель директива имеет часы только, чтобы доказать, что переменная обновляется ...

var myApp = angular.module('myApp',[]); 

myApp.directive('inViewport', function($timeout) { 
    return { 
     restrict: 'A', 
     scope: false, // ensure scope is same as parents 
     link: function(scope, element, attr) { 
     angular.element(window).bind('scroll', function() { 
      console.log('Called'); 
      $timeout(function() { 
      scope.inView++; 
      }, 0); 
     }); 
     } 
    }; 
    }); 

    myApp.directive('widget', function() { 
    return { 
     restrict: 'AE', 
     transclude: false, 
     template: '<p>This is a widget</p>', 
     link: function(scope) { 
     scope.inView = 0; 
     console.log('In Viewport: ', scope.inView); // Null 

     scope.$watch('inView', function(newVal, oldVal) { 
      console.log('Updated by the child directive: ', scope.inView); 
     }); 
     } 
    } 
    }); 

function MyCtrl($scope) { 
    $scope.name = 'Angular Directive Stuff'; 
}