2013-05-10 54 views
38

这里是角度noob。我正在创建一个递归显示问题和子问题树的指令。我在模板中使用了一个链接,它在范围内调用一个函数。由于某种原因,它不会调用editQuestion()方法。ng-click在指令模板中不起作用

下面的代码和小提琴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()); 
    } 
    }; 
}); 

理解任何帮助,将不胜感激。

回答

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> 

而且您的问题指令现在预计在其范围内的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()); 
    } 
    }; 
}); 

请注意我们如何在ng-click中定位question。这是你在回调函数中定位参数的方法。另外请注意,on-edit我们正在通过您的choices指令,我们的目标是subQuestion。这是因为question已经保留在ngRepeat的内部,所以我们需要区分这两者。

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

+0

感谢。我通过在指令中添加了ng-click =“onEdit()”而弄错了。 – Aravind 2015-07-13 09:28:07

+0

@Langdon感谢分享。这帮助我解决了我遇到的问题。在我的模板中,我在指令中有<按钮ng-click =“doSomethingInMainCtrl({{twowaybound.value}})”>按钮,并且在看到您的示例后,我在twowaybound.value周围取出大括号,直到解析器错误。 – 2017-04-15 15:29:04

8

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

您希望在指令和父代之间建立绑定,因此,当指令调用ngClick函数时,它会触发承载指令的模块。

要么你可以定义在指令本身,或设置通过的directive definition object

下面范围部分结合的方法就这么说明点火NG-点击不同的作用域事件plunker(输出到控制台)

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

2

兰登的May10 '13答案是正确的。 为了演示目的,我精简了兰登的小提琴代码,并将其从148行角度降低到23行角度。
我还添加了一些功能,可以通过函数调用方法将参数值作为MouseEvent对象传递,并检索函数中的所述值。

以下是JSFIDDLE后面的代码和信用,应该很容易遵循。

http://jsfiddle.net/BeyondLogical/evjzoo30/

--Html--

<div ng-controller="FormCtrl"> 
    <questions on-edit="editQuestion(ev,question)" ></questions> 
</div> 

--AngularJS--

var app = angular.module('myApp', []); 
function FormCtrl ($scope) { 
    $scope.editQuestion = function (ev,question) { 
     //ev returns a MouseEvent object 
     alert("ev: " + ev); 
     //this is how you get the 'data' attribute set in the span tag below 
     alert("ev-data: " + ev.target.attributes.data.value); 
    }; 
} 
app.directive('questions', function($compile) { 
    var tpl = 
    '<span ng-click="onEdit({ev: $event, myName: question})" data="This sentence would probably be replaced with a mustache brace parameter, example: {{someValue}}, returning a value from the scope." style="cursor:pointer;">Click Me</span>'; 
    return { 
     restrict: 'E', 
     terminal: true, 
     scope: { onEdit: '&' }, 
     template: tpl, 
     link: function(scope, element, attrs) { 
      $compile(element.contents())(scope.$new()); 
     } 
    }; 
}); 

贷,
兰登 - ng-click doesn't work within the template of a directive

马克Rajcok - AngularJS getting $event from a directive(Langdo n您还可以得到一个助攻问问号答案)

PavanAsTechie - Access attribute value inside non-directive controller function和帕万的的jsfiddle - http://jsfiddle.net/brettdewoody/FAeJq/(尤其是帕文的代码下面一行):alert(obj.target.attributes.data.value);

1

任何人来到这个与并试图用代码来做到这一点即没有运行在您的指令中,请检查您是否使用选项替换为

如:

angular.module('app').directive('myDirective', function() { 
return { 
    template: '<div ng-click="clicked()"></div>', 
    scope: { 
     options: "=" 
    }, 
    replace: true, //<---- Change this to false 
    restrict: 'E', 
    controller: function ($scope) { 

     $scope.clicked = function(){ 
     console.log("Clicked"); 
     } 
    } 
    }; 
}