2

I've read the most of similar topics, but my question is still unanswered.

I hava directive:

directive.repeatable = function () { return {
    restrict: 'A',
    scope: {
        data: '=repeatableData',
        add: '@'
    },
    controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
        $scope.add = function() {
            console.log("ADD");
        }

    }]
}

I need to have an isolated scope and yet need to expose and add method to nested DOM elements:

<div repeatable repeatable-data="data">
    <div ng-repeat="item in data">
      {{ item }}
    </div>
    <button ng-click="add()">Add</button>
</div>

How can I access add() method of parent directive? Tried: $parent.add(), $scope.$parent.add(), add: '&add'. But I guess I just don't get it.

P.S. I cannot really access the data property of the repeatable directive, instead, both repeatable-data and item in data point to the same "model".

Aleksandr Makov
  • 2,820
  • 3
  • 37
  • 62
  • can you explain what you want to achieve ? I cannot understand why you use directives this way – Ilan Frumer Jan 20 '14 at 11:11
  • @IlanFrumer, well, I need to fill a model, with list of objects, each of which has to have a structured element. In other words I need to build a picture selector, where I can add different pictures with different settings into 1 collection. The `repeatable` directive itself is linked to a model (collection store), `repeatable-data` holds template of object that collection will be filled with... In the end I need to get something like: `[{"url":"image1.jpg","alignment":"left"},{"url":"image2.jpg","alignment":"right"}]`. Kinda hard to explain :) – Aleksandr Makov Jan 20 '14 at 11:23
  • And `add` method adds an element, that is ready to receive a selected image url. – Aleksandr Makov Jan 20 '14 at 11:24
  • I tried to answer your question with my basic understanding. If you reject it maybe I would understand your app constrains. – Ilan Frumer Jan 20 '14 at 11:36
  • @IlanFrumer, thank you. I've upvoted your answer, because it will work. However, I cannot use templates and I found a way to do it — I have to recompile element contents with isolated scope: `$compile($element.contents())($scope);` – Aleksandr Makov Jan 20 '14 at 12:01
  • 2
    Is transclusion not an option? Then , your add button is part of the template (can just be inline string). The button will be part of the isolated scope, with access to `add` and the transcluded ngRepeat will still sit in the scope of the directives parent controller. I've used this technique a number of times for adding new items to existing arrays using only pure utility functions. – fooby Jan 20 '14 at 12:09
  • I updated my answer with $transclude. – Ilan Frumer Jan 20 '14 at 12:31
  • @fooby, yes, that would do it. Absolutely misused it initially. Thank you. – Aleksandr Makov Jan 20 '14 at 12:53

1 Answers1

2

UPDATE

Check my other answer: Why I can't access the right scope?

If you really want the inner content to be part of the isolated scope you can do it like so:

app.directive('repeatable', function () { 
  return {
    restrict: 'A',
    transclude: true,
    scope: {
        data: '=repeatableData',
        add: '@'
    },
    link: function(scope, elm, attr, ctrl, $transclude) {

      $transclude(scope, function(clone){
        elm.append(clone);
      });

      scope.add = function() {
          console.log("ADD");
      }

    }

  }  
});
Community
  • 1
  • 1
Ilan Frumer
  • 32,059
  • 8
  • 70
  • 84