AngularJS передает параметры в шаблоне директивы контроллеру



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



.directive('nodeList', function($compile) {
return {
restrict: 'E',
terminal: true,
scope: {
nodes: '=ngModel',
deleteArticle: '&',
editArticle: '&'
},
link: function ($scope, $element, $attrs) {
if (angular.isArray($scope.nodes)) {
$element.append('<accordion close-others="true"><node ng-repeat="item in nodes" ng-model="item" delete-article="deleteArticle(node_item)" edit-article="editArticle(node_item)"></node></accordion>');
}
$compile($element.contents())($scope.$new());
}
};
})

.directive('node', function($compile) {
return {
restrict: 'E',
terminal: true,
scope: {
node: '=ngModel',
deleteArticle: '&',
editArticle: '&'
},
link: function ($scope, $element, $attrs) {
if (angular.isArray($scope.node.Options) && $scope.node.Options.length > 0) {
$element.append('<accordion-group><accordion-heading>{{node.Title}} <a href="javascript:void(0)" ng-click="editArticle({node_item: node})" data-toggle="modal" data-target="#new-article" class="action"><i class="glyphicon glyphicon-edit"></i></a></accordion-heading><node-list ng-model="node.Options"></node-list>{{node.Content}}</accordion-group>');
} else {
$element.append('<accordion-group><accordion-heading>{{node.Title}} <a href="javascript:void(0)" ng-click="editArticle({node_item: node})" data-toggle="modal" data-target="#new-article" class="action"><i class="glyphicon glyphicon-edit"></i></a></accordion-heading>{{node.Content}}</accordion-group>');
}
$compile($element.contents())($scope.$new());
}
};
})


И такой html:



<node-list ng-model="articles" delete-article="deleteArticle(node_item)" edit-article="editArticle(node_item)"></node-list>


И в контроллере:



$scope.editArticle = function(vArticle) {}


Когда у меня есть только одна директива-все понятно, но как передать параметры, когда моя директива вызывает другую директиву? это реально? и каким образом?

610   4  

4 ответов:

Вам просто нужно изменить очень маленький кусочек вашего кода, чтобы ваш вызов функции получил аргумент правильно

В вашей директиве nodeList вызовите ваш узел следующим образом:

<node ng-repeat="item in nodes" ng-model="item" delete-article="deleteArticle({node_item: node_item})" edit-article="editArticle({node_item: node_item})"></node>

И в вашей директиве node вызовите свой nodeList следующим образом:

<node-list ng-model="node.Options" delete-article="deleteArticle({node_item: node_item})" edit-article="editArticle({node_item: node_item})"></node-list>

Так что ссылка "node_item" передается правильно среди детей детей детей... к самому верхнему родителю (ваш контроллер:)

Взгляните на это: плунжер

Причина:

Ваш имеет свою собственную область, вам нужно передать "node_item" в родительскую область (ваш контроллер), просто! Сложность заключается в том, что функция вызывается внутри области внука (), поэтому вам снова нужно передать "node_item" от внука к ребенку.

Вам также не нужно создавать новую область видимости при вызове compile. Объект $ scope, который у вас есть, также был новая область из родительской области.

Вы можете взаимодействовать между директивами, используя контроллер и делая эту зависимость явной. Простой пример:

var myApp = angular.module('myApp', [])
  .directive('foo', function () {
    return {
      restrict: 'E',
      controller: function ($scope) {
        this.property = 'something';
      },
      link: function (scope, element) {
      }
    };
  })
  .directive('bar', function() {
    return {
      require: '^foo',
      link: function (scope, element, attrs, fooCtrl) {
          console.log(fooCtrl.property);
        scope.value = fooCtrl.property;
      }
    }
  })

Здесь директива bar объявляет зависимость от директивы foo как заключающую директиву. Поэтому директивы могут взаимодействовать, так как функция link передает дополнительный аргумент. Поэтому этот HTML-фрагмент будет отображать something:

<div ng-app="myApp">
    <foo><bar>{{ value }}</bar></foo>
</div>

Вы можете играть с этим примером в этом JSFiddle.

Директива NodeList

Предоставьте API контроллера из вашей директивы nodeList, которую ваши дочерние директивы узлов могут вызывать для удаления или редактирования статьи.

controller: function ($scope) {
    this.deleteArticle = function (node) {
        var index = $scope.nodes.indexOf(node);
        if (index >= 0) {
            $scope.nodes.splice(index, 1);
            $scope.$emit('articleDeleted', node);
        }

    }
    this.editArticle = function (node) {
        var index = $scope.nodes.indexOf(node);
        if (index >= 0) {
            $scope.$emit('articleEdited', node);
        }

    }
}

Директива Узла

В директиве node вручную скомпилируйте директиву nodeList, чтобы избежать рекурсии, и добавьте ссылки для вызова API контроллера nodeList:

link: function ($scope, $element, $attrs, nodeListController) {
    var template = angular.element('<node-list ng-model="node.nodes" ng-hide="node.hidden"></node-list>');
     $element.append(template);
     $compile(template)($scope);

      $scope.delete = function (node) {
          nodeListController.deleteArticle(node);
      }

      $scope.edit = function (node) {
          nodeListController.editArticle(node);
      }
}

Родительский Контроллер:

Используйте $emit для уведомления пользователей о том, что узел был изменен или удален.

$scope.$on('articleEdited', function (evt, node) {
    alert('Edited ' + node.Title);
});
$scope.$on('articleDeleted', function (evt, node) {
    alert('Deleted ' + node.Title);
});

   var app = angular.module('app', []);
   var ctrl = app.controller('ctrl', function($scope, $rootScope) {
     $scope.nodes = [{
       Title: 'Title 1',
       nodes: [{
         Title: 'Title 1.1',
         nodes: []
       }, {
         Title: 'Title 1.2',
         nodes: []
       }]
     }, {
       Title: 'Title 2',
       nodes: [{
         Title: 'Title 2.1',
         nodes: [{
           Title: 'Title 2.1.1',
           nodes: []
         }, {
           Title: 'Title 2.1.2',
           nodes: []
         }]
       }, {
         Title: 'Title 2.2',
         nodes: [{
           Title: 'Title 2.2.1',
           nodes: []
         }, {
           Title: 'Title 2.2.2',
           nodes: []
         }, {
           Title: 'Title 2.2.3',
           nodes: []
         }, {
           Title: 'Title 2.2.4',
           nodes: []
         }]
       }]
     }];
     $scope.$on('articleEdited', function(evt, node) {
       alert('Edited ' + node.Title);
     });
     $scope.$on('articleDeleted', function(evt, node) {
       alert('Deleted ' + node.Title);
     });


   });
   app.directive('nodeList', function($parse) {
     return {
       restrict: 'E',
       scope: {
         nodes: '=ngModel'
       },
       template: '<div close-others="true"><node ng-repeat="item in nodes" ng-model="item" ></node></div>',
       controller: function($scope) {
         this.deleteArticle = function(node) {
           var index = $scope.nodes.indexOf(node);
           if (index >= 0) {
             $scope.nodes.splice(index, 1);
             $scope.$emit('articleDeleted', node);
           }

         }
         this.editArticle = function(node) {

           var index = $scope.nodes.indexOf(node);
           if (index >= 0) {
             $scope.$emit('articleEdited', node);
           }

         }
       },
       link: function($scope, $element, $attrs) {}
     };
   });

   app.directive('node', function($compile) {
     return {
       restrict: 'E',
       require: '^nodeList',
       scope: {
         node: '=ngModel'
       },
       controller: function($scope) {

       },
       template: '<div><span ng-click="node.hidden = !node.hidden">{{node.Title}}</span><a href="#" ng-click="edit(node)">Edit</a> <a href="#" ng-click="delete(node)">Delete</a></div>',
       link: function($scope, $element, $attrs, nodeListController) {
         var template = angular.element('<node-list ng-model="node.nodes" ng-hide="node.hidden"></node-list>');
         $element.append(template);
         $compile(template)($scope);

         $scope.delete = function(node) {
           nodeListController.deleteArticle(node);
         }

         $scope.edit = function(node) {
           nodeListController.editArticle(node);
         }
       }
     };
   });
  div {
    margin-left: 20px;
  }
<!DOCTYPE html>
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>

<body ng-app="app" ng-controller="ctrl">
  <node-list ng-model="nodes">
  </node-list>
</body>

</html>

Вы можете использовать сервис для передачи любого параметра, который вы используете Вам нужно будет добавить триггер, чтобы получить информацию при создании директивы этот триггер должен получить информацию от сервиса и использовать ее Если он будет создан и получит неопределенный параметр, то это будет первая директива

У меня нет рабочего кода, но эта концепция будет работать.

Comments

    Ничего не найдено.