Angular noob在这里。我正在创建一个指令,以递归方式显示问题树和子问题。我在模板中使用一个链接来调用范围内的函数。出于某种原因,它不会调用editQuestion()
方法。
这是代码和小提琴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());
}
};
});
理解这一点的任何帮助将不胜感激。
答案 0 :(得分:38)
你有一个范围问题。由于您在指令中使用了隔离范围scope: { value: '=' }
,因此它无法再访问具有editQuestion
的控制器范围。
您需要将editQuestion
传递给指令的范围,以便它知道如何调用它。这通常很简单,但由于你的无限递归指令结构,其中选择可以包括问题,它会变得有点棘手。这是一个工作小提琴:
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());
}
};
});
注意我们如何定位question
中的ng-click
。这是您在回调函数中定位参数的方法。另请注意我们on-edit
指示choices
如何传递给subQuestion
指令,我们的目标是question
。这是因为ngRepeat
已在{{1}}内保留,因此我们需要区分这两者。
到目前为止,这可能是我在Angular学习最困难的概念。一旦了解了范围在控制器,指令和其他指令之间如何工作,Angular的世界就是你的。 :)
答案 1 :(得分:7)
这是范围问题。该指令的ng-click调用当前作用域的editQuestion&amp; removeQuestion方法,它们在指令的作用域中不存在,因为它们是在包含指令的模块中定义的(即父作用域)。
您希望在指令和父指令之间建立绑定,因此当指令调用ngClick函数时,它将触发托管指令的模块。
您可以在指令本身中定义方法,也可以通过directive definition object的范围部分设置绑定
这是一个说明在不同范围触发ng-click事件(输出到控制台)的plunker
答案 2 :(得分:2)
兰登的5月10日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
Mark Rajcok - AngularJS getting $event from a directive(兰登也得到了一个问题马克答案的协助)
PavanAsTechie - Access attribute value inside non-directive controller function和Pavan的JSFIDDLE - http://jsfiddle.net/brettdewoody/FAeJq/(特别是Pavan的以下代码行):alert(obj.target.attributes.data.value);
答案 3 :(得分: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");
}
}
};
}