ng-click在指令的模板中不起作用

Mad*_*han 38 angularjs angularjs-directive angularjs-scope

Angular noob在这里.我正在创建一个指令,以递归方式显示问题树和子问题.我在模板中使用一个链接来调用范围内的函数.出于某种原因,它不会调用该editQuestion()方法.

这是代码和小提琴http://jsfiddle.net/madhums/n9KNv/

HTML:

<div ng-controller="FormCtrl">
  <questions value="survey.questions"></questions>
</div>
Run Code Online (Sandbox Code Playgroud)

使用Javascript:

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

function FormCtrl ($scope) {
  $scope.editQuestion = function (question) {
    alert('abc');
  };
  $scope.survey = {
    // ...
  }
}


app.directive('questions', function($compile) {
  var tpl = '<ol ui-sortable' +
    ' ng-model="value"' +
    ' class="list">' +
    '  <li ng-repeat="question in value | filter:search"' +
    '     <a href="" class="question">' +
    '       {{ question.name }}' +
    '     </a>' +
    '     <span class="muted">({{ question.type }})</span>' +
    '     <a href="" class="danger" ng-click="removeQuestion(question)">remove</a>' +
    '     <a href="" class="blue" ng-click="editQuestion(question)">edit</a>' +
    '     <choices value="question.choices"></choices>' +
    '  </li>' +
    '</ol>';

  return {
    restrict: 'E',
    terminal: true,
    scope: { value: '=' },
    template: tpl,
    link: function(scope, element, attrs) {
        $compile(element.contents())(scope.$new());
    }
  };
});

app.directive('choices', function($compile) {
  var tpl = '<ul class="abc" ng-repeat="choice in value">'+
    '  <li>' +
    '    {{ choice.name }}' +
    '    <span class="muted">' +
    '      ({{ choice.questions.length }} questions)' +
    '    </span>' +
    '' +
    '    <a href=""' +
    '      ng-click="addQuestions(choice.questions)"' +
    '      tooltip="add sub questions">' +
    '      +' +
    '    </a>' +
    '' +
    '    <questions value="choice.questions"></questions>'
    '  </li>' +
    '</ul>';

  return {
    restrict: 'E',
    terminal: true,
    scope: { value: '=' },
    template: tpl,
    link: function(scope, element, attrs) {
        $compile(element.contents())(scope.$new());
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

任何帮助理解这一点将不胜感激.

Lan*_*don 38

你有一个范围问题.由于您在指令中使用了隔离范围scope: { value: '=' },因此它不再具有访问您的控制器范围的权限editQuestion.

您需要传递editQuestion给指令的范围,以便它知道如何调用它.这通常很简单,但由于你的无限递归指令结构,其中选择可以包括问题,它会变得有点棘手.这是一个工作小提琴:

http://jsfiddle.net/n9KNv/14/

HTML现在包含对editQuestion以下内容的引用:

<div ng-controller="FormCtrl">
    <questions value="survey.questions" on-edit="editQuestion(question)"></questions>
</div>
Run Code Online (Sandbox Code Playgroud)

而您的问题指令现在需要onEdit在其范围内有一个属性:

app.directive('questions', function($compile) {
  var tpl = '<ol ui-sortable' +
    ' ng-model="value"' +
    ' class="list">' +
    '  <li ng-repeat="question in value | filter:search"' +
    '     <a href="" class="question">' +
    '       {{ question.name }}' +
    '     </a>' +
    '     <span class="muted">({{ question.type }})</span>' +
      '     <a href="" class="blue" ng-click="onEdit({question: question})">edit</a>' +
      '     <choices value="question.choices" on-edit="onEdit({question: subQuestion})"></choices>' +
    '  </li>' +
    '</ol>';

  return {
    restrict: 'E',
    terminal: true,
      scope: { value: '=', onEdit: '&' },
    template: tpl,
    link: function(scope, element, attrs) {
        $compile(element.contents())(scope.$new());
    }
  };
});

app.directive('choices', function($compile) {
  var tpl = '<ul class="abc" ng-repeat="choice in value">'+
    '  <li>' +
    '    {{ choice.name }}' +
    '    <span class="muted">' +
    '      ({{ choice.questions.length }} questions)' +
    '    </span>' +
    '' +
      '    <questions value="choice.questions" on-edit="onEdit({subQuestion: question})"></questions>'
    '  </li>' +
    '</ul>';

  return {
    restrict: 'E',
    terminal: true,
      scope: { value: '=', onEdit: '&' },
    template: tpl,
    link: function(scope, element, attrs) {
        $compile(element.contents())(scope.$new());
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

请注意,我们如何定位questionng-click.这是您在回调函数中定位参数的方法.另外请注意,在on-edit我们传递给您的choices指令时,我们的目标是什么subQuestion.这是因为question已经预留了内部ngRepeat,所以我们需要区分这两者.

到目前为止,这可能是我在Angular中学习最困难的概念.一旦了解了范围在控制器,指令和其他指令之间如何工作,Angular的世界就是你的.:)


Jas*_*son 7

这是范围问题.指令的ng-click调用当前作用域的editQuestion和removeQuestion方法,这些方法在指令的作用域中不存在,因为它们是在包含指令的模块中定义的(即父作用域).

您希望在指令和父指令之间建立绑定,因此当指令调用ngClick函数时,它将触发托管指令的模块.

您可以在指令本身中定义方法,也可以通过指令定义对象的scope部分设置绑定

这是一个说明在不同范围触发ng-click事件的plunker(输出到控制台)

http://plnkr.co/edit/9XfXCpU6lhUOqD6nbVuQ?p=preview