2

I have nested directives.

I send data from the first one the the second.

The problem is that I lose the the binding to the main scope.

This is my code: Plunker

(clicking the button changes the value in the main scope but not in the directive)

angular.module('app', [])

.controller('MainCtrl', function($scope) {
  
  $scope.change = function(){
    var id = Math.floor((Math.random() * 4) + 0);
    var val = Math.floor((Math.random() * 100) + 1);

    $scope.data.items[id].id = val;
  }
  $scope.data = {
    items: [{
      id: 1,
      name: "first"
    }, {
      id: 2,
      name: "second"
    }, {
      id: 3,
      name: "third"
    }, {
      id: 4,
      name: "forth"
    }]
  }
})

.directive('firstDirective', function($compile) {
  return {

    replace: true,
    restrict: 'A',
    scope: {
      data: '='
    },
    link: function(scope, element, attrs) {

      var template = '';
      angular.forEach(scope.data, function(item, key) {
        var sss = JSON.stringify(item).replace(/"/g, "'"); 
        var tmp = '<div>' +
          '<div second-directive data="' + sss + '"></div>' +
          '</div>';
          
          template = template + tmp;

      });
            element.html(template);
            $compile(element.contents())(scope);
    }
  }
})

.directive('secondDirective', function() {
   var comp = function(element, attrs){
      var data = JSON.parse(attrs.data.replace(/'/g, "\""));
      var template = '<div class="second-directive">' +
        '<h4>Directive 2</h4>' +
        'ID :' + data.id + '<br />' +
        'Name : ' + data.name +
        '</div>';

      element.replaceWith(template);
    
  }
 
  return {

    replace: true,
    restrict: 'A',
    compile: comp
  };
});
/* Put your css in here */

.second-directive{
  border:1px solid green;
  padding:4px;
  text-align:center;
  width:100px;
  height:auto;
  overflow:hidden;
  float:left;
  margin:2px;
}
<!DOCTYPE html>
<html ng-app="app">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="[email protected]" src="https://code.angularjs.org/1.3.15/angular.js" data-semver="1.3.15"></script>
    <script src="app.js"></script>
  </head> 

 <body ng-controller="MainCtrl">
   
    <h2>MainCtrl</h2>
    {{data}}
    <BR />
<button ng-click="change()">change value</button>
    <div first-directive data="data.items">
    </div>
  </body>

</html>

Thanks a lot

Avi

1 Answer 1

1

Not sure why you need nested directives. Seems to overcomplicate things. Why not just pass the data object to one directive and any changes you make in the parent controller will update in the directive as well.

http://plnkr.co/edit/gR3qBRmDotiUesS6DuyN?p=preview

index.html

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="[email protected]" src="https://code.angularjs.org/1.3.15/angular.js" data-semver="1.3.15"></script>
    <script src="app.js"></script>
  </head> 

 <body ng-controller="MainCtrl">

    <h2>MainCtrl</h2>
    {{data}}
    <BR />
<button ng-click="change()">change value</button>
    <div first-directive data="data.items">
    </div>
  </body>

</html>

template1.html

<div>
  <div class="second-directive" ng-repeat="item in data">
  <h4>Directive</h4>
        ID :{{ item.id }} <br />
        Name : {{item.name }}
  </div>
</div>

app.js

angular.module('app', [])

.controller('MainCtrl', function($scope) {

  $scope.change = function(){

    var id  = Math.floor((Math.random() * 4) + 0);
    var val = Math.floor((Math.random() * 100) + 1);

    $scope.data.items[id].id = val;
  }

  $scope.data = {
    items: [{
      id: 1,
      name: "first"
    }, {
      id: 2,
      name: "second"
    }, {
      id: 3,
      name: "third"
    }, {
      id: 4,
      name: "forth"
    }]
  };

})

.directive('firstDirective', function() {

  return {

    replace: true,
    templateUrl: 'template1.html',
    restrict: 'A',

    scope: {
      data: '='
    },

    link: function(scope, element, attrs) {


    }

  }

});

If you really need nested directives then you will need to look into the require option on the directive definition object where you can specify a parent directive controller which will be injected in the link function of the child directive. You can then access any properties on the parent directive scope in the child directive.

See: https://docs.angularjs.org/api/ng/service/$compile#directive-definition-object

Hope that helps.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.