3

У меня есть эти две директивы, один вложенными друг в друга:доступ к родительской области внутри директивы

<envato class="container content-view-container" data-ng-cloak data-ng-hide="spinner"> 
    <items data-ng-repeat="items in marketplaces"></items> 
</envato> 

И каждый из этих двух определяются как таковые:

Application.Envato.directive("envato", ["$timeout", function($timeout){ 

    var object = { 

     restrict : "E", 
     controller : "EnvatoAPIController", 
     transclude : true, 
     replace : true, 
     templateUrl : "templates/envato-view.php", 
     link : function(scope, element, attrs, controller) { 

      console.log(scope); 

      return controller.getLatestItems().then(function(data) { 



       scope.marketplaces = angular.fromJson(data); 
       scope.count = scope.marketplaces.length; 

       var tst = angular.element(element).find(".thumbnails"); 

       /* $timeout(function() { scope.swiper = new Swipe(document.getElementById('swiper-container')); }, 5000); */      
       scope.spinner = false; 
      }); 

     } 
    }; 

    return object; 
}]); 

Application.Envato.directive("items", function(){ 

    var iterator = [], 
     object = { 

      require : "^envato", 
      restrict : "E", 
      transclude : false, 
      replace : true, 
      templateUrl : "templates/envato-items-view.php", 
      link : function(scope, element, attrs, controller) { 

       iterator.push(element); 

       if (iterator.length === scope.$parent.$parent.count) { console.log(iterator); };          
      } 
     }; 

    return object; 
}); 

Много кода выше, возможно, не имеет большого смысла, потому что это часть более крупного приложения, но я надеюсь, что это будет сделано для моего вопроса. Я пытаюсь изменить свойство scope директивы envato по директиве items. Поскольку у меня есть итерация, и я хочу знать, когда это будет сделано, я могу выполнить еще одну операцию над добавленными элементами DOM во время этой итерации.

Например, предположим, что у меня будет scope.swipe, определяемый внутри директивы envato, и наблюдайте за изменениями. В директиве items, я буду смотреть, когда будет выполнен ng-repeat, а затем изменить указанное выше свойство области видимости scope.swipe. Это вызовет изменение внутри директивы envato, и теперь я узнаю, что я могу выполнить свою операцию.

Надеюсь, что я достаточно ясен, если не могу попробовать иметь больше кода, или я постараюсь быть более конкретным. Как я мог достичь того, что я только что описал выше?

EDIT: Я знаю, что с помощью: console.log(angular.element(element.parent()).scope()); внутри директивы items даст мне сферу envato директивы, но мне было интересно, если есть лучший способ сделать это.

ответ

4

Для такого рода межстраничной коммуникации я рекомендую определить API/метод в вашей директиве envato, которую может вызывать ваша директива items.

var EnvatoAPIController = function($scope) { 
    ... 
    this.doSomething = function() { ... } 
} 

Ваше items директива уже require ВЛЯЕТСЯ envato директиву, поэтому в функции связи вашего items директивы, просто вызвать API-интерфейс, при необходимости:

require : "^envato", 
link : function(scope, element, attrs, EnvatoCtrl) { 
    ... 
    if(scope.$last) { 
     EnvatoCtrl.doSomething(); 
    } 
} 

Что приятно об этом подходе является то, что он будет работать, даже если вы когда-нибудь решите использовать области выделения в своих директивах.

Директивы tabs и pane на домашней странице AngularJS используют этот механизм связи. См. https://stackoverflow.com/a/14168699/215945 для получения дополнительной информации. См. Также John's Directive to Directive Communication video.

1

Использовать scope.$eval('count') по адресу item Директива и разрешить угловое решение.

+0

И могу ли я применить к нему новые значения? – Roland

+0

Да, вы можете оценить любое [действительное угловое выражение] (http://docs.angularjs.org/guide/expression). Вы даже можете передавать локальные значения: 'scope. $ Eval ('scopeValue + localValue', {localValue: 15})'. Обратите внимание, что при настройке дочерняя область будет иметь значение изменено, а не родительское. В этом случае вы должны использовать функцию у родителя, чтобы вы могли изменить значение (т. Е. 'Scope. $ Eval ('changeValue (12345)')'). Посмотрите [здесь] (https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance) для получения дополнительной информации о наследовании области. Прочитайте документы ng-repeat. –

+0

Я вижу, поэтому, если я буду следить за свойством 'count' в родительской директиве' envato': 'scope. $ Watch (" count ", function (old, current, s) {console.log (old, current, s);}); '; часы будут видеть изменения вправо? Фактически, 'count' был всего лишь примером, я бы только установил свойство от false в true, чтобы продолжить другую операцию (или любое значение, которое говорит мне, что я могу продолжить применение функции, которая должна применяться после с шаблоном, добавленным в DOM/rendered). В этом случае было бы правильным выражением для изменения этого с помощью '$ eval'? – Roland

1

Я думаю, что вы ищете обратный вызов, который вызывается, когда заканчивается ng-repeat. Если это то, чего вы хотите, я создал скрипку. http://jsfiddle.net/wjFZR/.

В скрипке нет большого количества пользовательского интерфейса. Откройте консоль firebug и снова запустите скрипку. Вы увидите журнал. Этот журнал вызывается в конце ng-repeat, определенном в директиве cell.

$scope.rowDone = function(){ console.log($scope) } это функция обратного вызова, которая определена в директиве строки, которая будет вызвана, когда ng-repeat из директивы ячейки будет завершена.

Зарегистрировано таким образом.

<cell ng-repeat="data in rowData" repeat-done="rowDone()"></cell>

Отказ от ответственности: Я тоже новичок в angularjs.

+0

Я действительно нашел способ сделать это с предложениями @ CaioToOn и немного, но исследования. Я могу сделать это из директивы 'items', мне просто нужно проверить, когда' scope. $ Last' был переключен на true (это означает, что я только что зациклился на последнем элементе объекта). Но, к примеру, вы, например, были первой, но я хотел держать это в стороне от контроллера и держать его в директиве. – Roland

0

Я люблю ответ Марка, но я в конце концов создал директиву атрибута для сохранения областей ДИРЕКТИВ элемента к rootScope так:

myApp.directive('gScope', function(){ 
    return { 
     restrict: 'A', 
     replace: false, 
     transclude: false, 
     controller: "DirectiveCntl", 
     link: function(scope, element, attrs, controller) { 
      controller.saveScope(attrs.gScope); 
     } 
    } 
}); 

... 

function DirectiveCntl($scope, $rootScope) { 
    this.saveScope = function(id) { 
     if($rootScope.directiveScope == undefined) { 
      $rootScope.directiveScope = []; 
     } 
     $rootScope.directiveScope[id] = $scope; 
    }; 
} 

... 

<span>Now I can access the message here: {{directiveScope['myScopeId'].message}}</span> 
<other-directive> 
    <other-directive g-scope="myScopeId" ng-model="message"></other-directive> 
</other-directive> 

Примечания: В то время как это делает это легко и быстро собирать данные из всех различных директив он приходит с моим предостережением, что теперь вы должны обеспечить, чтобы потенциальная куча областей была должным образом управляема, чтобы избежать утечки памяти на страницах. Особенно, если вы используете ng-view для создания приложения на одну страницу.

1

Хммм, похоже, вы пытаетесь сделать это трудным для себя. В вашей директиве вы не установите свойство Область применения:

var object = { 
    restrict : "E", 
    transclude : true, 
    replace : true, 
    scope: true, 
    ... 

Настройка области видимости: {} даст вашей директиве в полностью изолированную новую область.

BUT setting scope: true даст вашей директиве полностью изолированную новую область, которая наследует родителя.

Этот метод используется для размещения модели в родительской директиве верхнего уровня и позволяет ей фильтровать все дочерние директивы.

Смежные вопросы