ng-click 在指令的模板中不起作用 [英] ng-click doesn't work within the template of a directive

查看:22
本文介绍了ng-click 在指令的模板中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

HTML:

<questions value="survey.questions"></questions>

Javascript:

var app = angular.module('myApp', []);函数 FormCtrl ($scope) {$scope.editQuestion = 函数(问题){警报('ABC');};$scope.survey = {//...}}app.directive('问题', 函数($compile) {var tpl = '<ol ui-sortable' +' ng-model="值"' +'类=列表">'+' <li ng-repeat="问题值| filter:search"' +' '+' {{ 问题名称 }}' +' </a>'+' <span class="静音">({{ 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>';返回 {限制:'E',终端:真的,范围:{值:'='},模板:tpl,链接:函数(范围,元素,属性){$compile(element.contents())(scope.$new());}};});app.directive('选择', function($compile) {var tpl = '
    '+' <li>'+' {{ 选择名}}' +' <span class="静音">'+' ({{choice.questions.length }} 个问题)' +' </span>'+'' +' <a href=""' +' ng-click="addQuestions(choice.questions)"' +' tooltip="添加子问题">'+' +' +' </a>'+'' +' <questions value="choice.questions"></questions>'' </li>'+'</ul>';返回 {限制:'E',终端:真的,范围:{值:'='},模板:tpl,链接:函数(范围,元素,属性){$compile(element.contents())(scope.$new());}};});

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

您遇到了范围问题.由于您在带有 scope: { value: '=' } 的指令中使用了隔离作用域,它不再可以访问具有 editQuestion 的控制器作用域.

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

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

HTML 现在包含对 editQuestion 的引用:

<questions value="survey.questions" on-edit="editQuestion(question)"></questions>

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

app.directive('questions', function($compile) {var tpl = '<ol ui-sortable' +' ng-model="值"' +'类=列表">'+' <li ng-repeat="问题值| filter:search"' +' '+' {{ 问题名称 }}' +' </a>'+' <span class="静音">({{ 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>';返回 {限制:'E',终端:真的,范围:{ 值:'=',onEdit:'&'},模板:tpl,链接:函数(范围,元素,属性){$compile(element.contents())(scope.$new());}};});app.directive('选择', function($compile) {var tpl = '<ul class="abc" ng-repeat="选择值">'+' <li>'+' {{ 选择名}}' +' <span class="静音">'+' ({{choice.questions.length }} 个问题)' +' </span>'+'' +' <questions value="choice.questions" on-edit="onEdit({subQuestion: question})"></questions>'' </li>'+'</ul>';返回 {限制:'E',终端:真的,范围:{ 值:'=',onEdit:'&'},模板:tpl,链接:函数(范围,元素,属性){$compile(element.contents())(scope.$new());}};});

注意我们如何在 ng-click 中定位 question.这就是您在回调函数中定位参数的方式.还要注意在 on-edit 中我们如何传递给您的 choices 指令,我们的目标是 subQuestion.这是因为question已经在ngRepeat里面保留了,所以我们需要区分两者.

这可能是迄今为止我在 Angular 中最难学习的概念.一旦你了解了控制器、指令和其他指令之间的作用域是如何工作的,Angular 的世界就是你的了.:)

Angular noob here. I am creating a directive to recursively display a tree of questions and sub questions. I am using a link in the template which calls a function within the scope. For some reason, it does't call the editQuestion() method.

Here's the code and the fiddle http://jsfiddle.net/madhums/n9KNv/

HTML:

<div ng-controller="FormCtrl">
  <questions value="survey.questions"></questions>
</div>

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());
    }
  };
});

Any help in understanding this would be appreciated.

解决方案

You've got a scope issue. Since you used isolated scope in your directive with scope: { value: '=' }, it no longer has access to your controller's scope that has editQuestion.

You need to pass editQuestion along to your directive's scope so it knows how to call it. This is typically pretty easy, but because of your infinitely recursive directive structure where choices can include questions, it gets a bit trickier. Here's a working fiddle:

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

The HTML now includes a reference to editQuestion:

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

And your questions directive now expects an onEdit attribute in its scope:

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());
    }
  };
});

Notice how we're targeting question in the ng-click. This is how you target arguments in callback functions. Also notice how in the on-edit we're passing to your choices directive, we're targeting subQuestion. This is because question is already reserved inside of the ngRepeat, so we need to differentiate between the two.

This was probably the hardest concept for me to learn in Angular so far. Once you understand how scope works between controllers, directives, and other directives, the world of Angular is yours. :)

这篇关于ng-click 在指令的模板中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆